| /* |
| * PUBLIC DOMAIN PCCTS-BASED C++ GRAMMAR (cplusplus.g, stat.g, expr.g) |
| * |
| * Authors: Sumana Srinivasan, NeXT Inc.; sumana_srinivasan@next.com |
| * Terence Parr, Parr Research Corporation; parrt@parr-research.com |
| * Russell Quong, Purdue University; quong@ecn.purdue.edu |
| * |
| * VERSION 1.1 |
| * |
| * SOFTWARE RIGHTS |
| * |
| * This file is a part of the ANTLR-based C++ grammar and is free |
| * software. We do not reserve any LEGAL rights to its use or |
| * distribution, but you may NOT claim ownership or authorship of this |
| * grammar or support code. An individual or company may otherwise do |
| * whatever they wish with the grammar distributed herewith including the |
| * incorporation of the grammar or the output generated by ANTLR into |
| * commerical software. You may redistribute in source or binary form |
| * without payment of royalties to us as long as this header remains |
| * in all source distributions. |
| * |
| * We encourage users to develop parsers/tools using this grammar. |
| * In return, we ask that credit is given to us for developing this |
| * grammar. By "credit", we mean that if you incorporate our grammar or |
| * the generated code into one of your programs (commercial product, |
| * research project, or otherwise) that you acknowledge this fact in the |
| * documentation, research report, etc.... In addition, you should say nice |
| * things about us at every opportunity. |
| * |
| * As long as these guidelines are kept, we expect to continue enhancing |
| * this grammar. Feel free to send us enhancements, fixes, bug reports, |
| * suggestions, or general words of encouragement at parrt@parr-research.com. |
| * |
| * NeXT Computer Inc. |
| * 900 Chesapeake Dr. |
| * Redwood City, CA 94555 |
| * 12/02/1994 |
| * |
| * Restructured for public consumption by Terence Parr late February, 1995. |
| * |
| * DISCLAIMER: we make no guarantees that this grammar works, makes sense, |
| * or can be used to do anything useful. |
| */ |
| /* |
| * 2001-2003 Version 2.0 September 2003 |
| * |
| * Some modifications were made to this file to support a project by |
| * Jianguo Zuo and David Wigg at |
| * The Centre for Systems and Software Engineering |
| * South Bank University |
| * London, UK. |
| * wiggjd@bcs.ac.uk |
| * blackse@lsbu.ac.uk |
| * |
| * These C++ functions are required to support the correct functioning of |
| * the CPP_parser.g definition of the C++ language. |
| */ |
| /* 2003-2004 Version 3.0 July 2004 |
| * Modified by David Wigg at London South Bank University for CPP_parser.g |
| */ |
| /* 2004-1005 Version 3.1 November 2005 |
| * Modified by David Wigg at London South Bank University for CPP_parser.g |
| * |
| * See MyReadMe.txt for further information |
| * |
| * This file is best viewed in courier font with tabs set to 4 spaces |
| */ |
| |
| extern "C" { |
| #ifndef WIN32 |
| #include <unistd.h> |
| #endif |
| } |
| |
| #include <iostream> |
| #include <stdio.h> |
| #include <string.h> |
| #include "../CPPParser/CPPParser.hpp" |
| |
| extern int |
| statementTrace; // Used to control selected tracing at statement level |
| // for testing and program verification purposes |
| |
| // Shorthand for a string of (qualifiedItemIs()==xxx||...) |
| int CPPParser::qualifiedItemIsOneOf( |
| QualifiedItem qiFlags, // Ored combination of flags |
| int lookahead_offset) { |
| QualifiedItem qi = qualifiedItemIs(lookahead_offset); |
| return (qi & qiFlags) != 0; |
| } |
| |
| // This is an important function, but will be replaced with |
| // an enhanced predicate in the future, once predicates |
| // and/or predicate guards can contain loops. |
| // |
| // Scan past the ::T::B:: to see what lies beyond. |
| // Return qiType if the qualified item can pose as type name. |
| // Note that T::T is NOT a type; it is a constructor. Also, |
| // class T { ... T...} yields the enclosed T as a ctor. This |
| // is probably a type as I separate out the constructor defs/decls, |
| // I want it consistent with T::T. |
| // |
| // In the below examples, I use A,B,T and example types, and |
| // a,b as example ids. |
| // In the below examples, any A or B may be a |
| // qualified template, i.e., A<...> |
| // |
| // T::T outside of class T yields qiCtor. |
| // T<...>::T outside of class T yields qiCtor. |
| // T inside of class T {...} yields qiCtor. |
| // T, ::T, A::T outside of class T yields qiType. |
| // a, ::a, A::B::a yields qiId |
| // a::b yields qiInvalid |
| // ::operator, operator, A::B::operator yield qiOPerator |
| // A::*, A::B::* yield qiPtrMember |
| // ::*, * yields qiInvalid |
| // ::~T, ~T, A::~T yield qiDtor |
| // ~a, ~A::a, A::~T::, ~T:: yield qiInvalid |
| |
| CPPParser::QualifiedItem CPPParser::qualifiedItemIs(int lookahead_offset) { |
| int offset = lookahead_offset + 1; |
| int final_type_idx = 0; |
| // Skip leading "::" |
| if (LT(offset)->getType() == SCOPE) { |
| offset++; |
| } |
| // Skip sequences of T:: or T<...>:: |
| // DW 11/02/05 Note that LT(offset)->getType() is not a "type" but a type of |
| // token, eg. ID |
| // printf("support.cpp qualifiedItemIs while reached offset %d %s type %d |
| // isType %d, isClass %d, guessing %d\n", |
| // offset,(LT(offset)->getText()).data(),LT(offset)->getType(),isTypeName((LT(offset)->getText()).data()),isClassName((LT(offset)->getText()).data()),inputState->guessing); |
| while (LT(offset)->getType() == ID && |
| isTypeName((LT(offset)->getText()).data())) { // If this type is the |
| // same as the last |
| // type, then ctor |
| if (final_type_idx != 0 && |
| strcmp((LT(final_type_idx)->getText()).data(), |
| (LT(offset)->getText()).data()) == 0) { // Like T::T |
| // As an extra check, do not allow T::T:: |
| if (LT(offset + 1)->getType() == SCOPE) { // printf("support.cpp |
| // qualifiedItemIs qiInvalid |
| // returned\n"); |
| return qiInvalid; |
| } else { // printf("support.cpp qualifiedItemIs qiCtor_1 returned %s %s |
| // %s \n", |
| // enclosingClass,(LT(lookahead_offset+1)->getText()).data(), |
| //(LT(final_type_idx)->getText()).data()); |
| return qiCtor; |
| } |
| } |
| |
| // Record this as the most recent type seen in the series |
| final_type_idx = offset; |
| |
| // Skip this token |
| offset++; |
| |
| // Skip over any template qualifiers <...> |
| // I believe that "T<..." cannot be anything valid but a template |
| if (LT(offset)->getType() == LESSTHAN) { |
| if (!skipTemplateQualifiers(offset)) { // printf("support.cpp |
| // qualifiedItemIs qiInvalid_2 |
| // returned\n"); |
| return qiInvalid; |
| } |
| // printf("support.cpp qualifiedItemIs template skipped, offset |
| // %d\n",offset); |
| // offset has been updated to token following <...> |
| } |
| |
| // Skip any "::" and keep going |
| if (LT(offset)->getType() == SCOPE) { |
| offset++; |
| } |
| // Otherwise series terminated -- last ID in the sequence was a type |
| else { |
| // Return ctor if last type is in containing class |
| // We already checked for T::T inside loop |
| if (strcmp(enclosingClass, (LT(final_type_idx)->getText()).data()) == |
| 0) { // Like class T T() |
| // printf("support.cpp qualifiedItemIs qiCtor_2 returned %s %s %s\n", |
| // enclosingClass,(LT(lookahead_offset+1)->getText()).data(), |
| // (LT(final_type_idx)->getText()).data()); |
| return qiCtor; |
| } else { // printf("support.cpp qualifiedItemIs qiType returned\n"); |
| return qiType; |
| } |
| } |
| } |
| |
| // LT(offset) is not an ID, or it is an ID but not a typename. |
| // printf("support.cpp qualifiedItemIs second switch reached with type |
| // %d\n",LT(offset)->getType()); |
| switch (LT(offset)->getType()) { |
| case ID: |
| // ID but not a typename |
| // Do not allow id:: |
| if (LT(offset + 1)->getType() == SCOPE) { |
| // printf("support.cpp qualifiedItemIs qiInvalid_3 returned\n"); |
| return qiInvalid; |
| } |
| if (strcmp(enclosingClass, (LT(offset)->getText()).data()) == |
| 0) { // Like class T T() |
| // printf("support.cpp qualifiedItemIs qiCtor_3 returned |
| // %s\n",enclosingClass); |
| return qiCtor; |
| } else { |
| if (isTypeName((LT(offset)->getText()).data())) { |
| return qiType; |
| } else { |
| // printf("support.cpp qualifiedItemIs qiVar returned\n"); |
| return qiVar; // DW 19/03/04 was qiVar Could be function, qiFun? |
| } |
| } |
| case TILDE: |
| // check for dtor |
| if (LT(offset + 1)->getType() == ID && |
| isTypeName((LT(offset + 1)->getText()).data()) && |
| LT(offset + 2)->getType() != SCOPE) { // Like ~B or A::B::~B |
| // Also (incorrectly?) matches ::~A. |
| // printf("support.cpp qualifiedItemIs qiDtor returned\n"); |
| return qiDtor; |
| } else { // ~a or ~A::a is qiInvalid |
| // printf("support.cpp qualifiedItemIs qiInvalid_4 returned\n"); |
| return qiInvalid; |
| } |
| break; |
| case STAR: |
| // Like A::* |
| // Do not allow * or ::* |
| if (final_type_idx == 0) { // Haven't seen a type yet |
| // printf("support.cpp qualifiedItemIs qiInvalid_5 returned\n"); |
| return qiInvalid; |
| } else { // printf("support.cpp qualifiedItemIs qiPtrMember returned\n"); |
| return qiPtrMember; |
| } |
| case OPERATOR: |
| // Like A::operator, ::operator, or operator |
| // printf("support.cpp qualifiedItemIs qiOperator returned\n"); |
| return qiOperator; |
| default: |
| // Something that neither starts with :: or ID, or |
| // a :: not followed by ID, operator, ~, or * |
| // printf("support.cpp qualifiedItemIs qiInvalid_6 returned\n"); |
| return qiInvalid; |
| } |
| } |
| |
| // Skip over <...>. This correctly handles nested <> and (), e.g: |
| // <T> |
| // < (i>3) > |
| // < T2<...> > |
| // but not |
| // < i>3 > |
| // |
| // On input, kInOut is the index of the "<" |
| // On output, if the return is true, then |
| // kInOut is the index of the token after ">" |
| // else |
| // kInOut is unchanged |
| int CPPParser::skipTemplateQualifiers(int &kInOut) { // Start after "<" |
| int offset = kInOut + 1; |
| |
| while (LT(offset)->getType() != GREATERTHAN) // scan to end of <...> |
| { |
| switch (LT(offset)->getType()) { |
| case EOF: |
| return 0; |
| case LESSTHAN: |
| if (!skipTemplateQualifiers(offset)) { |
| return 0; |
| } |
| break; |
| case LPAREN: |
| if (!skipNestedParens(offset)) { |
| return 0; |
| } |
| break; |
| default: |
| offset++; // skip everything else |
| break; |
| } |
| if (offset > MaxTemplateTokenScan) { |
| return 0; |
| } |
| } |
| |
| // Update output argument to point past ">" |
| kInOut = offset + 1; |
| return 1; |
| } |
| |
| // Skip over (...). This correctly handles nested (), e.g: |
| // (i>3, (i>5)) |
| // |
| // On input, kInOut is the index of the "(" |
| // On output, if the return is true, then |
| // kInOut is the index of the token after ")" |
| // else |
| // kInOut is unchanged |
| int CPPParser::skipNestedParens(int &kInOut) { // Start after "(" |
| int offset = kInOut + 1; |
| |
| while (LT(offset)->getType() != RPAREN) // scan to end of (...) |
| { |
| switch (LT(offset)->getType()) { |
| case EOF: |
| return 0; |
| case LPAREN: |
| if (!skipNestedParens(offset)) { |
| return 0; |
| } |
| break; |
| default: |
| offset++; // skip everything else |
| break; |
| } |
| if (offset > MaxTemplateTokenScan) { |
| return 0; |
| } |
| } |
| |
| // Update output argument to point past ")" |
| kInOut = offset + 1; |
| return 1; |
| } |
| |
| // Return true if "::blah" or "foo::bar<args>::..." found. |
| int CPPParser::scopedItem(int k) { |
| // printf("support.cpp scopedItem k %d\n",k); |
| return (LT(k)->getType() == SCOPE || |
| (LT(k)->getType() == ID && !finalQualifier(k))); |
| } |
| |
| // Return true if ID<...> or ID is last item in qualified item list. |
| // Return false if LT(k) is not an ID. |
| // ID must be a type to check for ID<...>, |
| // or else we would get confused by "i<3" |
| int CPPParser::finalQualifier(int k) { |
| if (LT(k)->getType() == ID) { |
| if (isTypeName((LT(k)->getText()).data()) && |
| LT(k + 1)->getType() == LESSTHAN) { // Starts with "T<". Skip <...> |
| k++; |
| skipTemplateQualifiers(k); |
| } else { // skip ID; |
| k++; |
| } |
| return (LT(k)->getType() != SCOPE); |
| } else { // not an ID |
| return 0; |
| } |
| } |
| |
| /* |
| * Return true if 's' can pose as a type name |
| */ |
| int CPPParser::isTypeName( |
| const char *s) { // printf("isTypeName entered with %s\n",s); |
| // To look for any type name only |
| return 1; |
| /* |
| CPPSymbol *cs = ( CPPSymbol * ) symbols->lookup( s,CPPSymbol::otTypename ); |
| |
| if ( cs==NULL ) |
| { |
| printf("support.cpp isTypeName %s not found\n",s); |
| return 0; |
| } |
| |
| // This should now be redundant |
| if ( cs->getType()==CPPSymbol::otTypedef|| |
| cs->getType()==CPPSymbol::otEnum|| |
| cs->getType()==CPPSymbol::otClass|| |
| cs->getType()==CPPSymbol::otStruct|| |
| cs->getType()==CPPSymbol::otUnion ) |
| { |
| return 1; |
| } |
| |
| return 0; |
| */ |
| } |
| |
| /* |
| * Return true if 's' is a class name (or a struct which is a class |
| * with all members public). |
| */ |
| int CPPParser::isClassName(const char *s) { |
| return 1; |
| /* |
| // To look for any type name omly |
| CPPSymbol *cs = ( CPPSymbol * ) symbols->lookup( s,CPPSymbol::otTypename ); |
| |
| if ( cs==NULL ) |
| { |
| printf("support.cpp isClassName %s not found\n",s); |
| return 0; |
| } |
| |
| if ( cs->getType()==CPPSymbol::otClass|| |
| cs->getType()==CPPSymbol::otStruct|| |
| cs->getType()==CPPSymbol::otUnion ) |
| { |
| return 1; |
| } |
| |
| return 0; |
| */ |
| } |
| |
| void CPPParser::beginDeclaration() {} |
| |
| void CPPParser::endDeclaration() {} |
| |
| void CPPParser::beginFunctionDefinition() { functionDefinition = 1; } |
| |
| void CPPParser::endFunctionDefinition() { |
| // Remove parameter scope |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| // printf("endFunctionDefinition remove parameter |
| // scope(%d):\n",symbols->getCurrentScopeIndex()); |
| symbols->removeScope(); // Remove symbols stored in current scope |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| // printf("endFunctionDefinition restoreScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| functionDefinition = 0; |
| } |
| |
| void CPPParser::beginConstructorDefinition() { functionDefinition = 1; } |
| |
| void CPPParser::endConstructorDefinition() { |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| // printf("endConstructorDefinition restoreScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| functionDefinition = 0; |
| } |
| |
| void CPPParser::beginConstructorDeclaration(const char *ctor) {} |
| |
| void CPPParser::endConstructorDeclaration() {} |
| |
| void CPPParser::beginDestructorDefinition() { functionDefinition = 1; } |
| |
| void CPPParser::endDestructorDefinition() { |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| // printf("endDestructorDefinition restoreScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| functionDefinition = 0; |
| } |
| |
| void CPPParser::beginDestructorDeclaration(const char *dtor) {} |
| |
| void CPPParser::endDestructorDeclaration() {} |
| |
| void CPPParser::beginParameterDeclaration() {} |
| |
| void CPPParser::beginFieldDeclaration() {} |
| |
| void CPPParser::declarationSpecifier(bool td, bool fd, StorageClass sc, |
| TypeQualifier tq, TypeSpecifier ts, |
| FunctionSpecifier fs) { |
| // printf("support.cpp declarationSpecifier td %d, fd %d, sc %d, tq %d, ts %d, |
| // fs %d\n", |
| // td,fd,sc,tq,ts,fs); |
| _td = td; // For typedef |
| _fd = fd; // For friend |
| _sc = sc; |
| _tq = tq; |
| _ts = ts; |
| _fs = fs; |
| } |
| |
| /* Symbols from declarators are added to the symbol table here. |
| * The symbol is added to external scope or whatever the current scope is, in |
| * the symbol table. |
| * See list of object types below. |
| */ |
| void CPPParser::declaratorID(const char *id, QualifiedItem qi) { |
| // printf("declaratorID entered for %s\n",id); |
| CPPSymbol *c; |
| // printf("support.cpp declaratorID line %d %s found, _ts = %d, _td = %d, qi = |
| // %d\n", |
| // LT(1)->getLine(),id,_ts,_td,qi); |
| if (qi == qiType || qi == qiNamespace) // Check for type declaration |
| { |
| c = new CPPSymbol(id, CPPSymbol::otTypedef); |
| if (c == NULL) panic("can't alloc CPPSymbol"); |
| symbols->defineInScope(id, c, externalScope); |
| if (statementTrace >= 2) { |
| printf( |
| "%d support.cpp declaratorID declare %s in external scope 1, " |
| "ObjectType %d\n", |
| LT(1)->getLine(), id, c->getType()); |
| } |
| // DW 04/08/03 Scoping not fully implemented |
| // Typedefs all recorded in 'external' scope and therefor never removed |
| } else if (qi == qiFun) // Check for function declaration |
| { |
| c = new CPPSymbol(id, CPPSymbol::otFunction); |
| if (c == NULL) panic("can't alloc CPPSymbol"); |
| symbols->define(id, c); // Add to current scope |
| if (statementTrace >= 2) { |
| printf( |
| "%d support.cpp declaratorID declare %s in current scope %d, " |
| "ObjectType %d\n", |
| LT(1)->getLine(), id, symbols->getCurrentScopeIndex(), c->getType()); |
| } |
| } else { |
| if (qi != qiVar) { |
| fprintf( |
| stderr, |
| "%d support.cpp declaratorID warning qi (%d) not qiVar (%d) for %s\n", |
| LT(1)->getLine(), qi, qiVar, id); |
| } |
| |
| c = new CPPSymbol(id, CPPSymbol::otVariable); |
| if (c == NULL) panic("can't alloc CPPSymbol"); |
| symbols->define(id, c); // Add to current scope |
| if (statementTrace >= 2) { |
| printf( |
| "%d support.cpp declaratorID declare %s in current scope %d, " |
| "ObjectType %d\n", |
| LT(1)->getLine(), id, symbols->getCurrentScopeIndex(), c->getType()); |
| } |
| } |
| } |
| /* These are the object types |
| 0 = otInvalid |
| 1 = otFunction |
| 2 = otVariable |
| 3 = otTypedef Note. 3-7 are type names |
| 4 = otStruct Note. 4, 5 & 7 are class names |
| 5 = otUnion |
| 6 = otEnum |
| 7 = otClass |
| 10 = otTypename |
| 11 = otNonTypename |
| */ |
| |
| void CPPParser::declaratorArray() {} |
| |
| void CPPParser::declaratorParameterList(int def) { |
| symbols->saveScope(); // Advance currentScope (lower level) |
| // printf("declaratorParameterList saveScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| } |
| |
| void CPPParser::declaratorEndParameterList(int def) { |
| if (!def) { |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| // printf("declaratorEndParameterList restoreScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| } |
| } |
| |
| void CPPParser::functionParameterList() { |
| symbols->saveScope(); // Advance currentScope (lower level) |
| // printf("functionParameterList saveScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| // DW 25/3/97 change flag from function to parameter list |
| functionDefinition = 2; |
| } |
| |
| void CPPParser::functionEndParameterList(int def) { |
| // If this parameter list is not in a definition then this |
| if (!def) { |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| // printf("functionEndParameterList restoreScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| } else { |
| // Change flag from parameter list to body of definition |
| functionDefinition = 3; |
| } |
| // Otherwise endFunctionDefinition removes the parameters from scope |
| } |
| |
| void CPPParser::enterNewLocalScope() { |
| symbols->saveScope(); // Advance currentScope (lower level) |
| // printf("enterNewLocalScope saveScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| } |
| |
| void CPPParser::exitLocalScope() { |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| // printf("exitLocalScope restoreScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| } |
| |
| void CPPParser::enterExternalScope() { // Scope has been initialised to 1 in |
| // CPPParser.init() in CPPParser.hpp |
| functionDefinition = 0; |
| } |
| |
| void CPPParser::exitExternalScope() { |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope s/b 2 |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope s/b 1 |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| |
| if (symbols->getCurrentScopeIndex() == 0) { |
| if (statementTrace >= 2) { |
| fprintf(stdout, "\nSupport exitExternalScope, scope now %d as required\n", |
| symbols->getCurrentScopeIndex()); |
| } |
| } else { |
| fprintf(stderr, "\nSupport exitExternalScope, scope now %d, should be 0\n", |
| symbols->getCurrentScopeIndex()); |
| } |
| } |
| |
| void CPPParser::classForwardDeclaration(TypeSpecifier ts, FunctionSpecifier fs, |
| const char *tag) |
| // classForwardDeclaration(const char *tag, TypeSpecifier ts, FunctionSpecifier |
| // fs) |
| { |
| CPPSymbol *c = NULL; |
| |
| // if already in symbol table as a class, don't add |
| // of course, this is incorrect as you can rename |
| // classes by entering a new scope, but our limited |
| // example basically keeps all types globally visible. |
| if (symbols->lookup(tag, CPPSymbol::otTypename) != NULL) { |
| CPPSymbol *cs = (CPPSymbol *)symbols->lookup(tag, CPPSymbol::otTypename); |
| if (statementTrace >= 2) { |
| printf( |
| "%d support.cpp classForwardDeclaration %s already stored in " |
| "dictionary, ObjectType %d\n", |
| LT(1)->getLine(), tag, cs->getType()); |
| } |
| return; |
| } |
| |
| switch (ts) { |
| case tsSTRUCT: |
| c = new CPPSymbol(tag, CPPSymbol::otStruct); |
| break; |
| case tsUNION: |
| c = new CPPSymbol(tag, CPPSymbol::otUnion); |
| break; |
| case tsCLASS: |
| c = new CPPSymbol(tag, CPPSymbol::otClass); |
| break; |
| } |
| |
| if (c == NULL) panic("can't alloc CPPSymbol"); |
| |
| symbols->defineInScope(tag, c, externalScope); |
| if (statementTrace >= 2) { |
| printf( |
| "%d support.cpp classForwardDeclaration declare %s in external scope, " |
| "ObjectType %d\n", |
| LT(1)->getLine(), tag, c->getType()); |
| } |
| |
| // If it's a friend class forward decl, put in global scope also. |
| // DW 04/07/03 No need if already in external scope. See above. |
| // if ( ds==dsFRIEND ) |
| // { |
| // CPPSymbol *ext_c = new CPPSymbol(tag, CPPSymbol::otClass); |
| // if ( ext_c==NULL ) panic("can't alloc CPPSymbol"); |
| // if ( symbols->getCurrentScopeIndex()!=externalScope ) // DW 04/07/03 |
| // Not sure this test is really necessary |
| // { |
| // printf("classForwardDeclaration |
| // defineInScope(externalScope)\n"); |
| // symbols->defineInScope(tag, ext_c, externalScope); |
| // } |
| // } |
| } |
| |
| void CPPParser::exitNamespaceScope() {} |
| |
| void CPPParser::beginClassDefinition(TypeSpecifier ts, const char *tag) { |
| CPPSymbol *c = NULL; |
| |
| // if already in symbol table as a class, don't add |
| // of course, this is incorrect as you can rename |
| // classes by entering a new scope, but our limited |
| // example basically keeps all types globally visible. |
| if (symbols->lookup(tag, CPPSymbol::otTypename) != NULL) { |
| symbols->saveScope(); // still have to use scope to collect members |
| // printf("support.cpp beginClassDefinition_1 saveScope() now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| if (statementTrace >= 2) { |
| printf( |
| "%d support.cpp beginClassDefinition classname %s already in " |
| "dictionary\n", |
| LT(1)->getLine(), tag); |
| } |
| return; |
| } |
| |
| switch (ts) { |
| case tsSTRUCT: |
| c = new CPPSymbol(tag, CPPSymbol::otStruct); |
| break; |
| case tsUNION: |
| c = new CPPSymbol(tag, CPPSymbol::otUnion); |
| break; |
| case tsCLASS: |
| c = new CPPSymbol(tag, CPPSymbol::otClass); |
| break; |
| } |
| if (c == NULL) panic("can't alloc CPPSymbol"); |
| |
| symbols->defineInScope(tag, c, externalScope); |
| |
| if (statementTrace >= 2) { |
| printf( |
| "%d support.cpp beginClassDefinition define %s in external scope (1), " |
| "ObjectType %d\n", |
| LT(1)->getLine(), tag, c->getType()); |
| } |
| |
| strcat(qualifierPrefix, tag); |
| strcat(qualifierPrefix, "::"); |
| |
| // add all member type symbols into the global scope (not correct, but |
| // will work for most code). |
| // This symbol lives until the end of the file |
| symbols->saveScope(); // Advance currentScope (lower level) |
| } |
| |
| void CPPParser::endClassDefinition() { |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| // remove final T:: from A::B::C::T:: |
| // upon backing out of last class, qualifierPrefix is set to "" |
| char *p = &(qualifierPrefix[strlen(qualifierPrefix) - 3]); |
| while (p > &(qualifierPrefix[0]) && *p != ':') { |
| p--; |
| } |
| if (p > &(qualifierPrefix[0])) p++; |
| *p = '\0'; |
| } |
| |
| void CPPParser::enumElement(const char *e) {} |
| |
| void CPPParser::beginEnumDefinition( |
| const char *e) { // DW 26/3/97 Set flag for new class |
| |
| // add all enum tags into the global scope (not correct, but |
| // will work for most code). |
| // This symbol lives until the end of the file |
| CPPSymbol *c = new CPPSymbol(e, CPPSymbol::otEnum); |
| symbols->defineInScope(e, c, externalScope); |
| if (statementTrace >= 2) { |
| printf( |
| "%d support.cpp beginEnumDefinition %s define in external scope, " |
| "ObjectType %d\n", |
| LT(1)->getLine(), e, c->getType()); |
| } |
| } |
| |
| void CPPParser::endEnumDefinition() {} |
| |
| void CPPParser::templateTypeParameter(const char *t) { |
| // DW 11/06/03 Symbol saved in templateParameterScope (0) |
| // as a temporary measure until scope is implemented fully |
| // This symbol lives until the end of the file |
| CPPSymbol *e = new CPPSymbol(t, CPPSymbol::otTypedef); // DW 22/03/05 |
| // CPPSymbol *e = new CPPSymbol(t, CPPSymbol::otClass); |
| if (e == NULL) panic("can't alloc CPPSymbol"); |
| // symbols->defineInScope(t, e, templateParameterScope); // DW 22/03/05 |
| // DW 10/08/05 Replaced to make template parameters local |
| symbols->defineInScope(t, e, externalScope); |
| // symbols->define(t,e); // Save template parameter in local scope |
| if (statementTrace >= 2) { |
| // printf("%d support.cpp templateTypeParameter declare %s in |
| // parameter |
| // scope (0), ObjectType %d\n", |
| printf( |
| "%d support.cpp templateTypeParameter declare %s in external scope " |
| "(1), ObjectType %d\n", |
| LT(1)->getLine(), t, e->getType()); |
| } |
| // printf("%d support.cpp templateTypeParameter declare %s in |
| // current |
| // scope %d, ObjectType %d\n", |
| // LT(1)->getLine(),t,symbols->getCurrentScopeIndex(),e->getType()); |
| } |
| |
| void CPPParser::beginTemplateDeclaration() { |
| symbols->saveScope(); // Advance currentScope (lower level) |
| // printf("Support beginTemplateDeclaration, Scope now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| } |
| |
| void CPPParser::endTemplateDeclaration() { |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| // printf("Support endTemplateDeclaration, Scope now |
| // %d\n",symbols->getCurrentScopeIndex()); |
| } |
| |
| void CPPParser::beginTemplateDefinition() {} |
| |
| void CPPParser::endTemplateDefinition() {} |
| |
| void CPPParser::beginTemplateParameterList() { |
| // DW 26/05/03 To scope template parameters |
| symbols->saveScope(); // Advance currentScope (lower level) |
| } |
| |
| void CPPParser::endTemplateParameterList() { |
| // DW 26/05/03 To end scope template parameters |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| } |
| |
| void CPPParser::exceptionBeginHandler() {} |
| |
| void CPPParser::exceptionEndHandler() { // remove parm elements from the |
| // handler scope |
| symbols->dumpScope(stdout); // Diagnostic - See CPPDictionary.hpp |
| symbols->removeScope(); // Remove symbols stored in current scope |
| symbols->restoreScope(); // Reduce currentScope (higher level) |
| } |
| |
| void CPPParser::end_of_stmt() { |
| #ifdef MYCODE |
| myCode_end_of_stmt(); |
| #endif // MYCODE |
| } |
| |
| void CPPParser::panic(const char *err) { |
| fprintf(stdout, "CPPParser: %s\n", err); |
| _exit(-1); |
| } |
| |
| /* DW 090204 leave out of support.cpp for the time being |
| // want to see how supplied routine in LLkParser works first |
| void CPPParser:: |
| tracein(char *r) |
| { |
| // testing |
| printf("support tracein entered\n"); |
| getchar(); |
| if ( !doTracing ) return; |
| for (int i=1; i<=traceIndentLevel; i++) |
| fprintf(stdout, " "); |
| traceIndentLevel++; |
| fprintf(stdout, "enter %s('%s %s')%s\n", |
| r, |
| (LT(1)->getText()).data(), |
| (LT(2)->getText()).data(), |
| inputState->guessing?" [guessing]":"" |
| ); |
| fflush(stdout); |
| } |
| |
| void CPPParser:: |
| traceout(char *r) |
| { |
| if ( !doTracing ) return; |
| traceIndentLevel--; |
| for (int i=1; i<=traceIndentLevel; i++) |
| fprintf(stdout, " "); |
| fprintf(stdout, "exit %s('%s %s')%s\n", |
| r, |
| (LT(1)->getText()).data(), |
| (LT(2)->getText()).data(), |
| inputState->guessing?" [guessing]":"" |
| ); |
| fflush(stdout); |
| } |
| */ |
| |
| // Functions which may be overridden by MyCode subclass |
| |
| void CPPParser::myCode_pre_processing(int argc, char *argv[]) {} |
| |
| void CPPParser::myCode_post_processing() {} |
| |
| void CPPParser::myCode_end_of_stmt() {} |
| |
| void CPPParser::myCode_function_direct_declarator(const char *id) { |
| // printf("support myCode_function_direct_declarator entered for %s\n",id); |
| } |