rfta-svn Mailing List for Refactoring Assistant (Page 2)
Brought to you by:
blep
You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
(35) |
May
|
Jun
|
Jul
|
Aug
(21) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
---|
From: <rft...@li...> - 2007-04-29 09:12:08
|
Revision: 32 http://rfta.svn.sourceforge.net/rfta/?rev=32&view=rev Author: blep Date: 2007-04-29 02:12:07 -0700 (Sun, 29 Apr 2007) Log Message: ----------- - fixed crash on wrong guessed self type detection in base classes. - fixed parsing of empty function body. - added overall stats to result Modified Paths: -------------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/test/testresultbrowser.py Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_014_inheritance_ns.cpp Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-28 20:28:02 UTC (rev 31) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-29 09:12:07 UTC (rev 32) @@ -89,6 +89,7 @@ bool scopeQualifiedLookUp_; bool isSelfType_; //ScopeManager scopeManager_; + LocatedSymbol selfTypeId_; }; } // namespace Rfta { Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-28 20:28:02 UTC (rev 31) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-29 09:12:07 UTC (rev 32) @@ -28,7 +28,10 @@ # ############################## A.7: Declaration ############################ ::declaration_seq - +( =>( ~( %T_EOF | '}' ) ) *declaration ?declaration_error ) + +( =>( ~( %T_EOF | '}' ) ) + declaration + |declaration_error + ) ::declaration namespace_definition @@ -217,9 +220,9 @@ ::fn_definition_skip_compound '{' - ( +( ~('{' | '}' | %T_EOF) ) - | +fn_definition_skip_compound - ) + ?( +( ~('{' | '}' | %T_EOF) ) + | +fn_definition_skip_compound + ) '}' ::ctor_member_initializer Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-28 20:28:02 UTC (rev 31) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-29 09:12:07 UTC (rev 32) @@ -158,6 +158,16 @@ CPPTL_DEBUG_ASSERT_UNREACHABLE; } } + // do not allow self type id . + if ( isSelfType_ ) + { + isSelfType_ = false; + if ( scopeQualifiedLookUp_ ) + typeId_ = &( decls_.declareOrResolveQualifiedType( selfTypeId_, *lookUpScope_ ) ); + else + typeId_ = &( decls_.declareOrResolveUnqualifiedType( selfTypeId_, *lookUpScope_ ) ); + } + TypeDeclaration *typeDecl = typeId_->isTypeDeclaration(); CPPTL_ASSERT_MESSAGE( typeDecl != 0, "Inherited type is not an aggregate." ); currentClassDecl_->addBaseClass( *typeDecl, AccessLevel( access ) ); @@ -252,6 +262,7 @@ { isSelfType_ = true; typeId_ = 0; + selfTypeId_ = *(typeId.start_); } else { Modified: rfta/trunk/test/testresultbrowser.py =================================================================== --- rfta/trunk/test/testresultbrowser.py 2007-04-28 20:28:02 UTC (rev 31) +++ rfta/trunk/test/testresultbrowser.py 2007-04-29 09:12:07 UTC (rev 32) @@ -189,17 +189,26 @@ def _makeIndex( self ): print '_makeIndex' suffix = '-parser.txt' - s = "<table><tr><td>Project</td><td>%ok</td><td>Pass/Fail</td><td>Decl.</td></tr>" + sall = "<table><tr><td>Project</td><td>%ok</td><td>Pass/Fail</td><td>Decl.</td></tr>" + s = '' + total_passed, total_failed,total_decls = (0,0,0) for path in glob.glob( os.path.join( TESTRESULT_PATH, '*' + suffix ) ): print 'Generating content for', path path = path[:-len(suffix)] info = self.getProjectInfo( os.path.split(path)[1] ) project_link = info.getProjectLink() - s+= "<tr><td>%s</td><td>%3.1f%%</td><td>%4d/%-4d</td><td>%d</td>" % ( + s+= "<tr><td>%s</td><td>%3.1f%%</td><td>%4d/%-4d</td><td>%d</td>\n" % ( project_link, 100.0 * len(info.passed) / float(max(1,len(info.status))), len(info.passed), len(info.failed), len(info.decls) ) - s += "</table>" - return self.makeHTML( s ) + total_passed += len(info.passed) + total_failed += len(info.failed) + total_decls += len(info.decls) + sall += "<tr><td>%s</td><td>%3.1f%%</td><td>%4d/%-4d</td><td>%d</td>\n" % ( + 'Overall', 100.0 * total_passed / float(max(1,total_failed+total_passed)), + total_passed, total_failed, total_decls ) + sall += s + sall += "</table>" + return self.makeHTML( sall ) def makeHTML( self, body, style = '' ): if style != '': Added: rfta/trunk/testdata/cxxparser_ut/t_class_014_inheritance_ns.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_014_inheritance_ns.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_014_inheritance_ns.cpp 2007-04-29 09:12:07 UTC (rev 32) @@ -0,0 +1,3 @@ +class C0014 : public C14::C14 +{ +}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-28 20:28:05
|
Revision: 31 http://rfta.svn.sourceforge.net/rfta/?rev=31&view=rev Author: blep Date: 2007-04-28 13:28:02 -0700 (Sat, 28 Apr 2007) Log Message: ----------- - fixed preprocessor skipping EOL comment type - fixed infinite loop due to wrong skipping in parser rules. Modified Paths: -------------- rfta/trunk/include/rfta/token.h rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/test_rftaparser/main.cpp rfta/trunk/test/rftaparser_test.py Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_013_error_recovery1.cpp Modified: rfta/trunk/include/rfta/token.h =================================================================== --- rfta/trunk/include/rfta/token.h 2007-04-27 22:04:09 UTC (rev 30) +++ rfta/trunk/include/rfta/token.h 2007-04-28 20:28:02 UTC (rev 31) @@ -223,7 +223,7 @@ case PPTokenType: case PPConditionalTokenType: { - // skip until next EOL, but handle line continuation + // skip until next EOL, but handle line continuation and comments bool lineContinuationFound = false; while ( true ) { @@ -238,6 +238,8 @@ case T_LINECONT: lineContinuationFound = true; break; + case T_CPPCOMMENT: + return originalTokenId; case T_EOF: return originalTokenId; default: // skip anything else Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-27 22:04:09 UTC (rev 30) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-28 20:28:02 UTC (rev 31) @@ -142,21 +142,35 @@ ::member_specification +( =>( ~( %T_EOF | '}' ) ) - *( access_specification | member_declaration ) - ?member_declaration_error + *( access_specification + | member_declaration + | member_declaration_error + ) ) +# Attempts recovery at the first ';' found or after '}' skipping compound. ::member_declaration_error =>( ~( %T_EOF | '}' ) ) # look-ahead is not a end of declaration block, then error - $error_tokens=( ( +member_declaration__skip_token ?statement_skip_error_compound - | statement_skip_error_compound - ) ?';' ) + $error_tokens=( member_declaration_skip_tokens ?( ';' + | member_declaration_skip_compound + ) + | member_declaration_skip_compound + ) !handleDeclarationError[ $error_tokens ] -::member_declaration__skip_token - ~( %T_EOF | '{' | '}' | ';' ) +::member_declaration_skip_tokens + +( ~( %T_EOF | '{' | '}' | ';' ) ) +::member_declaration_skip_compound_tokens + +( ~( %T_EOF | '{' | '}' ) ) +::member_declaration_skip_compound + '{' + *( member_declaration_skip_compound_tokens + | member_declaration_skip_compound + ) + '}' + # X Y; => variable # X Y(); => function # X Y( ... ); => variable or function: declaration of unknown type named Y. @@ -199,10 +213,15 @@ ::fn_definition ?ctor_member_initializer - '{' - *( ~('{' | '}' | %T_EOF) | statement_skip_error_compound ) - '}' + fn_definition_skip_compound +::fn_definition_skip_compound + '{' + ( +( ~('{' | '}' | %T_EOF) ) + | +fn_definition_skip_compound + ) + '}' + ::ctor_member_initializer ':' identifier '(' skip_member_init_expression ')' *(',' identifier '(' skip_member_init_expression ')' ) Modified: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp 2007-04-27 22:04:09 UTC (rev 30) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-28 20:28:02 UTC (rev 31) @@ -105,7 +105,7 @@ , public Rfta::DeclarationVisitor { public: - DeclarationDumper( FILE *fout, + DeclarationDumper( FILE *fout, Rfta::DeclarationManager &declarationManager, Rfta::TokenContentManager &contentManager, const std::string &input ) @@ -116,13 +116,26 @@ { } - void printErrors( Rfta::EnumErrorInfo enumErrors ) + void printErrors( Rfta::EnumErrorInfo enumErrors, FILE *ferror ) { + typedef std::deque<Rfta::ErrorInfo> Errors; + Errors errors; while ( enumErrors.hasNext() ) + errors.push_front( enumErrors.next() ); + int currentLine = 0; + std::string::size_type offset = 0; + for ( Errors::const_iterator it = errors.begin(); it != errors.end(); ++it ) { - const Rfta::ErrorInfo &error = enumErrors.next(); + const Rfta::ErrorInfo &error = *it; + if ( error.start_ < offset ) + currentLine = std::count( input_.begin(), input_.begin() + error.start_, '\n' ); + else if ( error.start_ > offset ) + currentLine += std::count( input_.begin() + offset, input_.begin() + error.start_, '\n' ); + offset = error.start_; std::string msg = input_.substr( error.start_, error.end_ - error.start_); - fprintf( fout_, "#=> Error: %s\n%s\n", + fprintf( ferror, "#=> Error line %d (offset %d): %s\n%s\n", + currentLine, + offset, error.message_.c_str(), CppTL::quoteMultiLineString( msg ).c_str() ); } @@ -310,8 +323,10 @@ std::string file; bool noOutput; bool noLog; + bool hasDebug; bool isSilent; std::string input; + std::string debugFile; bool appendLog; bool appendOutput; Rfta::OptionsParser cmd; @@ -323,6 +338,8 @@ cmd.addDisableOption( 0, "log", noLog, "Disable logging" ); cmd.addIsPresentOption( 0, "log-append", appendLog, "Append to log file, don't truncate" ); cmd.addIsPresentOption( 0, "output-append", appendOutput, "Append to output file, don't truncate" ); + cmd.addIsPresentOption( 'd', "debug", hasDebug, "Enable parser logging" ); + cmd.addOption( 0, "debug-log", debugFile, "", "Set parser debug log path" ); try { cmd.parse( argc, argv ); @@ -349,13 +366,18 @@ OutputFileHandle foutput( output, !noOutput, appendOutput ); OutputFileHandle flog( log, !noLog, appendLog ); - if ( foutput.hasCreationFailed() || flog.hasCreationFailed() ) + OutputFileHandle fdebug( debugFile, hasDebug, false ); + if ( foutput.hasCreationFailed() + || flog.hasCreationFailed() + || fdebug.hasCreationFailed() ) + { return 1; + } Rfta::TokenContentManager contentManager; Rfta::CxxParser parser; - if ( !noLog ) - parser.enableTrace( contentManager, flog ); + if ( hasDebug ) + parser.enableTrace( contentManager, fdebug ); Rfta::FileId fileId = 1234; Rfta::TokenStream tokenStream( input.c_str(), input.c_str() + input.length(), contentManager, @@ -381,7 +403,7 @@ DeclarationDumper dumper( foutput, declarationManager, contentManager, input ); dumper.visitGlobalNamespaceScope( declarationManager.getGlobalNamespaceScope() ); if ( parserAction->hasError() ) - dumper.printErrors( parserAction->enumErrors() ); + dumper.printErrors( parserAction->enumErrors(), flog ); } if ( !matched || parserAction->hasError() ) Modified: rfta/trunk/test/rftaparser_test.py =================================================================== --- rfta/trunk/test/rftaparser_test.py 2007-04-27 22:04:09 UTC (rev 30) +++ rfta/trunk/test/rftaparser_test.py 2007-04-28 20:28:02 UTC (rev 31) @@ -20,7 +20,7 @@ if __name__ == '__main__': class ParserTestRunner(rftatest.TestRunner): def __init__( self ): - rftatest.TestRunner.__init__( self, PARSER_PATH, extra_flags = ('--no-log',) ) + rftatest.TestRunner.__init__( self, PARSER_PATH ) #, extra_flags = ('--no-log',) ) self.output_file_suffix = '-parser.txt' ParserTestRunner().runZippedProjects( RESULT_DIR ) Added: rfta/trunk/testdata/cxxparser_ut/t_class_013_error_recovery1.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_013_error_recovery1.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_013_error_recovery1.cpp 2007-04-28 20:28:02 UTC (rev 31) @@ -0,0 +1,4 @@ +class C0012A +{ + C0012A_MACRO() +}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-27 22:04:11
|
Revision: 30 http://rfta.svn.sourceforge.net/rfta/?rev=30&view=rev Author: blep Date: 2007-04-27 15:04:09 -0700 (Fri, 27 Apr 2007) Log Message: ----------- - added support for anonymous namespace - fixed infinite loop - fixed a few miss-handling of anonymous types. Modified Paths: -------------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/include/rfta/cxxtype.h rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/src/lib_rftaparser/cxxtype.cpp rfta/trunk/src/test_rftaparser/main.cpp rfta/trunk/test/rftaparser_test.py Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_ns_003_anonymous.cpp Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-27 06:52:34 UTC (rev 29) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-27 22:04:09 UTC (rev 30) @@ -32,7 +32,7 @@ public: // overridden from CxxParserDelegate // namespace - virtual void declareAndEnterNamespace(const TokenScannerPosRange &id); + virtual void declareAndEnterNamespace(const TokenScannerPosRange &ns, const TokenScannerPosRange &id); virtual void exitNamespaceDeclaration(); // enum Modified: rfta/trunk/include/rfta/cxxtype.h =================================================================== --- rfta/trunk/include/rfta/cxxtype.h 2007-04-27 06:52:34 UTC (rev 29) +++ rfta/trunk/include/rfta/cxxtype.h 2007-04-27 22:04:09 UTC (rev 30) @@ -198,13 +198,15 @@ class AnonymousNamespaceScope : public NamespaceScope { public: - AnonymousNamespaceScope( GlobalNamespaceScope &parentScope ); + AnonymousNamespaceScope( const Location &location, + GlobalNamespaceScope &parentScope ); public: // overridden from NamespaceScope virtual void accept( ScopeVisitor &visitor ); virtual Scope *getOutterScope() const; private: + Location location_; GlobalNamespaceScope &parentScope_; }; @@ -431,7 +433,7 @@ GlobalNamespaceScope &getGlobalNamespaceScope(); NamespaceScope &declareNamespace( const LocatedSymbol &id, NamespaceScope &scope ); - //ScopeId declareAnynonmousNamespace( const Location &location, ScopeId scope ); + NamespaceScope &declareAnonymousNamespace( const Location &location ); EnumTypeDecl &declareEnum( const LocatedSymbol &id, Scope &scope ); EnumTypeDecl &declareAnonymousEnum( const Location &location, Scope &scope ); EnumValueDecl &declareEnumValue( const LocatedSymbol &id, EnumTypeDecl &enumType ); @@ -469,6 +471,7 @@ GlobalNamespaceScope globalNamespace_; CppTL::BatchAllocator<NamespaceDecl> namespaceDeclAlloc_; + CppTL::BatchAllocator<AnonymousNamespaceScope> anonymousNamespaceScopeAlloc_; CppTL::BatchAllocator<EnumTypeDecl> enumTypeDeclAlloc_; CppTL::BatchAllocator<EnumValueDecl> enumValueAlloc_; CppTL::BatchAllocator<ClassDecl> classDeclAlloc_; Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-27 06:52:34 UTC (rev 29) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-27 22:04:09 UTC (rev 30) @@ -76,9 +76,9 @@ # ::namespace_definition - 'namespace' $id=(?identifier) + $ns=('namespace') $id=(?identifier) '{' - !declareAndEnterNamespace[$id] + !declareAndEnterNamespace[$ns,$id] @[exitNamespaceDeclaration] namespace_body '}' @@ -148,7 +148,9 @@ ::member_declaration_error =>( ~( %T_EOF | '}' ) ) # look-ahead is not a end of declaration block, then error - $error_tokens=( +member_declaration__skip_token ?statement_skip_error_compound ?';' ) + $error_tokens=( ( +member_declaration__skip_token ?statement_skip_error_compound + | statement_skip_error_compound + ) ?';' ) !handleDeclarationError[ $error_tokens ] ::member_declaration__skip_token Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-27 06:52:34 UTC (rev 29) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-27 22:04:09 UTC (rev 30) @@ -51,11 +51,20 @@ void -CxxParserAction::declareAndEnterNamespace(const TokenScannerPosRange &id) +CxxParserAction::declareAndEnterNamespace(const TokenScannerPosRange &ns, + const TokenScannerPosRange &id) { - NamespaceScope &namespaceScope = decls_.declareNamespace( *(id.start_), - *namespaceScopes_.top() ); - namespaceScopes_.push( &namespaceScope ); + NamespaceScope *namespaceScope; + if ( id.length() == 0 ) + { + namespaceScope = &decls_.declareAnonymousNamespace( *(ns.start_) ); + } + else + { + namespaceScope = &decls_.declareNamespace( *(id.start_), + *namespaceScopes_.top() ); + } + namespaceScopes_.push( namespaceScope ); } Modified: rfta/trunk/src/lib_rftaparser/cxxtype.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-27 06:52:34 UTC (rev 29) +++ rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-27 22:04:09 UTC (rev 30) @@ -184,8 +184,10 @@ // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -AnonymousNamespaceScope::AnonymousNamespaceScope( GlobalNamespaceScope &parentScope ) +AnonymousNamespaceScope::AnonymousNamespaceScope( const Location &location, + GlobalNamespaceScope &parentScope ) : parentScope_( parentScope ) + , location_( location ) { } @@ -713,16 +715,18 @@ new (namespaceDeclAlloc_.allocate()) NamespaceDecl( id, scope ); return *namespaceScope; } -// -// -//ScopeId -//DeclarationManager::declareAnynonmousNamespace( const Location &location, -// ScopeId scope ) -//{ -//} -// -// + +NamespaceScope & +DeclarationManager::declareAnonymousNamespace( const Location &location ) +{ + NamespaceScope *namespaceScope = + new (anonymousNamespaceScopeAlloc_.allocate()) + AnonymousNamespaceScope( location, getGlobalNamespaceScope() ); + return *namespaceScope; +} + + EnumTypeDecl & DeclarationManager::declareEnum( const LocatedSymbol &id, Scope &scope ) { Modified: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp 2007-04-27 06:52:34 UTC (rev 29) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-27 22:04:09 UTC (rev 30) @@ -232,7 +232,11 @@ Rfta::TypeDeclaration *typeDecl = type.isTypeDeclaration(); if ( typeDecl != 0 ) { - CppTL::ConstString typeName = getSymbolText( typeDecl->getSymbol() ); + CppTL::ConstString typeName; + if ( typeDecl->hasSymbol() ) + typeName = getSymbolText( typeDecl->getSymbol() ); + else + typeName = "<anonymous class>"; Rfta::Scope *scope = &( typeDecl->getDeclarationScope() ); while ( scope ) { @@ -248,7 +252,10 @@ } else // class { - typeName = getText( scope->getScopeSymbol() ) + "::" + typeName; + if ( scope->getScopeSymbol() == Rfta::nullTextId() ) + typeName = "<anonymous>::" + typeName; + else + typeName = getText( scope->getScopeSymbol() ) + "::" + typeName; scope = scope->getOutterScope(); } } @@ -347,7 +354,8 @@ Rfta::TokenContentManager contentManager; Rfta::CxxParser parser; - parser.enableTrace( contentManager, flog ); + if ( !noLog ) + parser.enableTrace( contentManager, flog ); Rfta::FileId fileId = 1234; Rfta::TokenStream tokenStream( input.c_str(), input.c_str() + input.length(), contentManager, Modified: rfta/trunk/test/rftaparser_test.py =================================================================== --- rfta/trunk/test/rftaparser_test.py 2007-04-27 06:52:34 UTC (rev 29) +++ rfta/trunk/test/rftaparser_test.py 2007-04-27 22:04:09 UTC (rev 30) @@ -20,7 +20,7 @@ if __name__ == '__main__': class ParserTestRunner(rftatest.TestRunner): def __init__( self ): - rftatest.TestRunner.__init__( self, PARSER_PATH ) + rftatest.TestRunner.__init__( self, PARSER_PATH, extra_flags = ('--no-log',) ) self.output_file_suffix = '-parser.txt' ParserTestRunner().runZippedProjects( RESULT_DIR ) Added: rfta/trunk/testdata/cxxparser_ut/t_ns_003_anonymous.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_ns_003_anonymous.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_ns_003_anonymous.cpp 2007-04-27 22:04:09 UTC (rev 30) @@ -0,0 +1,6 @@ +namespace +{ + namespace Test3 + { + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-27 06:52:36
|
Revision: 29 http://rfta.svn.sourceforge.net/rfta/?rev=29&view=rev Author: blep Date: 2007-04-26 23:52:34 -0700 (Thu, 26 Apr 2007) Log Message: ----------- - added parsing of empty base class initializer Modified Paths: -------------- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_012_ctor_base.cpp Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-26 21:47:30 UTC (rev 28) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-27 06:52:34 UTC (rev 29) @@ -202,9 +202,12 @@ '}' ::ctor_member_initializer - ':' identifier skip_braced_expression - *(',' identifier skip_braced_expression) + ':' identifier '(' skip_member_init_expression ')' + *(',' identifier '(' skip_member_init_expression ')' ) +::skip_member_init_expression + *( skip_braced_expression | ~(')' | %T_EOF) ) + ::storage_class_specifier $storageClass=( +( 'auto' | 'register' Added: rfta/trunk/testdata/cxxparser_ut/t_class_012_ctor_base.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_012_ctor_base.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_012_ctor_base.cpp 2007-04-27 06:52:34 UTC (rev 29) @@ -0,0 +1,27 @@ +class C0012A +{ + C0012A( int x ) + : x_( 3 ) + { + } + + int x_; +}; + + +class C0012B : public C0012A +{ + C0012B() + : C0012A( 7 ) + { + } +}; + + +class C0012C : public C0012B +{ + C0012C() + : C0012B() + { + } +}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-26 21:47:32
|
Revision: 28 http://rfta.svn.sourceforge.net/rfta/?rev=28&view=rev Author: blep Date: 2007-04-26 14:47:30 -0700 (Thu, 26 Apr 2007) Log Message: ----------- - added parsing of class destructor and constructor with member initialization. Modified Paths: -------------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_010_dtor.cpp rfta/trunk/testdata/cxxparser_ut/t_class_011_ctor_member.cpp Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-26 07:14:10 UTC (rev 27) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-26 21:47:30 UTC (rev 28) @@ -52,8 +52,8 @@ virtual void setMemberVisibility(const TokenScannerPosRange &access); // type id - virtual void beginTypeId(const TokenScannerPosRange &gscope); - virtual void addTypeIdScope(const TokenScannerPosRange &scope); + virtual void beginScope(const TokenScannerPosRange &gscope); + virtual void addScope(const TokenScannerPosRange &scope); virtual void endTypeId(const TokenScannerPosRange &typeId); virtual void setBuiltInsTypeSpecifier(const TokenScannerPosRange &builtins); virtual void setTypeSpecifier(const TokenScannerPosRange &cv1, const TokenScannerPosRange &cv2); @@ -79,14 +79,14 @@ TokenContentManager &contentManager_; LocatedSymbol className_; ClassDecl *currentClassDecl_; - Scope *typeIdScope_; + Scope *lookUpScope_; /// typeId_ will be set on the following events: /// - Beginning enum declaration /// - Exiting class declaration /// - Ending a (scoped) type identifier Type *typeId_; unsigned int typeSpecifierQualifier_; - bool typeIdQualifiedLookUp_; + bool scopeQualifiedLookUp_; bool isSelfType_; //ScopeManager scopeManager_; }; Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-26 07:14:10 UTC (rev 27) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-26 21:47:30 UTC (rev 28) @@ -1,3 +1,5 @@ +#todo check that identifier in destructor sequence is self type. + ::translation_unit ?(declaration_seq) %T_EOF @@ -121,6 +123,7 @@ #- opt(::) nested-name-specifier opt(template) unqualified-id ::member_declaration simple_declaration + | ';' # friend_simple_declaration # | typedef_simple_declaration # | class_forward_declaration @@ -159,21 +162,23 @@ ::simple_declaration ?storage_class_specifier ?function_specifier - type_specifier - ( ';' - | ( => declarationTypeIsSelfType[] fn_suffix ( ';' | fn_definition ) ) - | ( init_declarator ( fn_definition - | ?initializer *( ',' init_declarator ?initializer) ';' - ) - ) - ) + ( + type_specifier + ( ';' + | ( => declarationTypeIsSelfType[] fn_suffix ( ';' | fn_definition ) ) + | ( init_declarator ( fn_definition + | ?initializer *( ',' init_declarator ?initializer) ';' + ) + ) + ) + | scope '~' identifier '(' ')' fn_throw_clause ( fn_definition | ';' ) + ) ::init_declarator *ptr_operator ( 'operator' ( operator | simple_type_specifier ) *fn_suffix - | '~' identifier '(' ')' #destructor | $idVar=(identifier) ?fn_suffix !setDeclarator[$idVar] ) @@ -185,13 +190,21 @@ *(~(')')) ')' ?($cv1=(cv_qualifier_seq)) + fn_throw_clause + +::fn_throw_clause ?( 'throw' '(' ?type_list ')' ) ::fn_definition + ?ctor_member_initializer '{' *( ~('{' | '}' | %T_EOF) | statement_skip_error_compound ) '}' +::ctor_member_initializer + ':' identifier skip_braced_expression + *(',' identifier skip_braced_expression) + ::storage_class_specifier $storageClass=( +( 'auto' | 'register' @@ -279,7 +292,10 @@ +( skip_block_initializer | ~( '}' | %T_EOF ) ) '}' +::scope + $gscope=(?'::') !beginScope[$gscope] + *( $scope=(identifier) '::' !addScope[$scope] ) + ::type_id - $gscope=(?'::') !beginTypeId[$gscope] - *( $scope=(identifier) '::' !addTypeIdScope[$scope] ) + scope $typeId=(identifier) !endTypeId[$typeId] \ No newline at end of file Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-26 07:14:10 UTC (rev 27) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-26 21:47:30 UTC (rev 28) @@ -28,7 +28,7 @@ , contentManager_( contentManager ) , currentEnumDecl_( 0 ) , currentClassDecl_( 0 ) - , typeIdScope_( 0 ) + , lookUpScope_( 0 ) , typeId_( 0 ) , isSelfType_( false ) { @@ -203,35 +203,35 @@ void -CxxParserAction::beginTypeId(const TokenScannerPosRange &gscope) +CxxParserAction::beginScope(const TokenScannerPosRange &gscope) { if ( gscope.length() == 0 ) { - typeIdScope_ = &getCurrentScope(); - typeIdQualifiedLookUp_ = false; + lookUpScope_ = &getCurrentScope(); + scopeQualifiedLookUp_ = false; } else { - typeIdScope_ = &decls_.getGlobalNamespaceScope(); - typeIdQualifiedLookUp_ = true; + lookUpScope_ = &decls_.getGlobalNamespaceScope(); + scopeQualifiedLookUp_ = true; } typeId_ = 0; } void -CxxParserAction::addTypeIdScope(const TokenScannerPosRange &scope) +CxxParserAction::addScope(const TokenScannerPosRange &scope) { - if ( typeIdQualifiedLookUp_ ) + if ( scopeQualifiedLookUp_ ) { - typeIdScope_ = &( decls_.declareOrResolveQualifiedScope( *(scope.start_), - *typeIdScope_ ) ); + lookUpScope_ = &( decls_.declareOrResolveQualifiedScope( *(scope.start_), + *lookUpScope_ ) ); } else { - typeIdScope_ = &( decls_.declareOrResolveUnqualifiedScope( *(scope.start_), - *typeIdScope_ ) ); - typeIdQualifiedLookUp_ = true; + lookUpScope_ = &( decls_.declareOrResolveUnqualifiedScope( *(scope.start_), + *lookUpScope_ ) ); + scopeQualifiedLookUp_ = true; } } @@ -239,7 +239,7 @@ void CxxParserAction::endTypeId(const TokenScannerPosRange &typeId) { - if ( typeIdScope_->isSelfTypeId( typeId.start_->text_ ) ) + if ( lookUpScope_->isSelfTypeId( typeId.start_->text_ ) ) { isSelfType_ = true; typeId_ = 0; @@ -247,10 +247,10 @@ else { isSelfType_ = false; - if ( typeIdQualifiedLookUp_ ) - typeId_ = &( decls_.declareOrResolveQualifiedType( *(typeId.start_), *typeIdScope_ ) ); + if ( scopeQualifiedLookUp_ ) + typeId_ = &( decls_.declareOrResolveQualifiedType( *(typeId.start_), *lookUpScope_ ) ); else - typeId_ = &( decls_.declareOrResolveUnqualifiedType( *(typeId.start_), *typeIdScope_ ) ); + typeId_ = &( decls_.declareOrResolveUnqualifiedType( *(typeId.start_), *lookUpScope_ ) ); } } @@ -356,7 +356,7 @@ CxxParserAction::setDeclarator(const TokenScannerPosRange &idVar) { if ( isSelfType_ ) - typeId_ = CppTL::checkedCast( typeIdScope_, CppTL::Type<Type *>() ); + typeId_ = CppTL::checkedCast( lookUpScope_, CppTL::Type<Type *>() ); CPPTL_ASSERT_MESSAGE( typeId_ != 0, "Invalid typeId_" ); decls_.declareSymbol( *(idVar.start_), *typeId_, getCurrentScope() ); } Added: rfta/trunk/testdata/cxxparser_ut/t_class_010_dtor.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_010_dtor.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_010_dtor.cpp 2007-04-26 21:47:30 UTC (rev 28) @@ -0,0 +1,22 @@ +class C0010 +{ + ~C0010(); +}; + +class C0010B +{ + virtual ~C0010B(); +}; + + +class C0010C +{ + virtual ~C0010C() throw() + { + } +}; + + +C0010B::~C0010B() +{ +} \ No newline at end of file Added: rfta/trunk/testdata/cxxparser_ut/t_class_011_ctor_member.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_011_ctor_member.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_011_ctor_member.cpp 2007-04-26 21:47:30 UTC (rev 28) @@ -0,0 +1,24 @@ +class C0011 +{ + C0011() + : x_( 3 ) + { + } + + int x_; +}; + + +class C0011B +{ + C0011B(); + + int x_; + int y_; +}; + +C0011B::C0011B() + : x_( 3 ) + , y_( 7 ) +{ +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-26 07:14:25
|
Revision: 27 http://rfta.svn.sourceforge.net/rfta/?rev=27&view=rev Author: blep Date: 2007-04-26 00:14:10 -0700 (Thu, 26 Apr 2007) Log Message: ----------- - added parsing of throw clause in function suffix. Modified Paths: -------------- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_009_fn_throws.cpp Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-25 22:05:39 UTC (rev 26) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-26 07:14:10 UTC (rev 27) @@ -185,7 +185,7 @@ *(~(')')) ')' ?($cv1=(cv_qualifier_seq)) - # add throw clause... + ?( 'throw' '(' ?type_list ')' ) ::fn_definition '{' @@ -205,6 +205,10 @@ | 'virtual' | 'explicit') ) +::type_list + type_specifier *ptr_operator + *( ',' type_specifier *ptr_operator ) + # type specifier used for conversion operator ::simple_type_specifier ?($cv1=(cv_qualifier_seq)) Added: rfta/trunk/testdata/cxxparser_ut/t_class_009_fn_throws.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_009_fn_throws.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_009_fn_throws.cpp 2007-04-26 07:14:10 UTC (rev 27) @@ -0,0 +1,6 @@ +class C0009 +{ + const char *what() throw(); + + const char *whatThrowsMany() throw(C0009, int, const char *); +}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-25 22:05:44
|
Revision: 26 http://rfta.svn.sourceforge.net/rfta/?rev=26&view=rev Author: blep Date: 2007-04-25 15:05:39 -0700 (Wed, 25 Apr 2007) Log Message: ----------- - added simple variable declaration dump - fixed self type variable declaration Modified Paths: -------------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/include/rfta/cxxparserbase.h rfta/trunk/include/rfta/cxxtype.h rfta/trunk/include/rfta/forwards.h rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/src/lib_rftaparser/cxxtype.cpp rfta/trunk/src/test_rftaparser/main.cpp Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_008_self_pointer.cpp Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-24 06:49:08 UTC (rev 25) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-25 22:05:39 UTC (rev 26) @@ -57,9 +57,11 @@ virtual void endTypeId(const TokenScannerPosRange &typeId); virtual void setBuiltInsTypeSpecifier(const TokenScannerPosRange &builtins); virtual void setTypeSpecifier(const TokenScannerPosRange &cv1, const TokenScannerPosRange &cv2); - virtual bool declarationTypeIsSelfType(); + // declarator + virtual void setDeclarator(const TokenScannerPosRange &idVar); + private: void addError( const TokenScannerPosRange &tokens, const char *message ); @@ -85,6 +87,7 @@ Type *typeId_; unsigned int typeSpecifierQualifier_; bool typeIdQualifiedLookUp_; + bool isSelfType_; //ScopeManager scopeManager_; }; Modified: rfta/trunk/include/rfta/cxxparserbase.h =================================================================== --- rfta/trunk/include/rfta/cxxparserbase.h 2007-04-24 06:49:08 UTC (rev 25) +++ rfta/trunk/include/rfta/cxxparserbase.h 2007-04-25 22:05:39 UTC (rev 26) @@ -163,6 +163,7 @@ fprintf( logFile_, "%s%s %s %s\n", indent_.c_str(), prefix, name, buffer.c_str() ); + fflush( logFile_ ); } void dumpTokens( CppTL::StringBuffer &tokensText ) const Modified: rfta/trunk/include/rfta/cxxtype.h =================================================================== --- rfta/trunk/include/rfta/cxxtype.h 2007-04-24 06:49:08 UTC (rev 25) +++ rfta/trunk/include/rfta/cxxtype.h 2007-04-25 22:05:39 UTC (rev 26) @@ -118,6 +118,7 @@ virtual TextId getScopeSymbol() const = 0; virtual TypeDeclaration *resolveQualifiedType( TextId id ) const = 0; TypeDeclaration *resolveUnqualifiedType( TextId id ) const; + virtual bool isSelfTypeId( TextId id ) const; private: Scope( const Scope &other ); @@ -158,6 +159,7 @@ virtual void visitEnumTypeDecl( EnumTypeDecl &enumTypeDecl ) = 0; virtual void visitEnumValueDecl( EnumValueDecl &enumValueDecl ) = 0; virtual void visitClassDecl( ClassDecl &classDecl ) = 0; + virtual void visitSymbolDecl( SymbolDecl &symbolDecl ) = 0; }; @@ -353,6 +355,7 @@ virtual Scope *resolveQualifiedScope( TextId id ); virtual Scope *getOutterScope() const; virtual TypeDeclaration *resolveQualifiedType( TextId id ) const; + virtual bool isSelfTypeId( TextId id ) const; public: // overridden from TypeDeclaration virtual void accept( DeclarationVisitor &visitor ); @@ -374,6 +377,28 @@ }; +class SymbolDecl : public Declaration +{ +public: + SymbolDecl( const LocatedSymbol &id, + Type &type ); + + const LocatedSymbol &getDeclSymbol() const; + + Type &getDeclType() const; + +private: // overridden from Declaration + virtual void accept( DeclarationVisitor &visitor ); + +private: + SymbolDecl( const SymbolDecl &other ); + SymbolDecl &operator =( const SymbolDecl &other ); + + LocatedSymbol id_; + Type &type_; +}; + + class BuiltInType : public Type { public: @@ -434,6 +459,10 @@ Type &getBuildInType( BuiltInSign sign, BuiltInKind type ); + SymbolDecl &declareSymbol( const LocatedSymbol &id, + Type &type, + Scope &scope ); + private: void initializeBuiltIns(); void setBuiltIn( BuiltInKind type, BuiltInSign sign, Type &builtinType ); @@ -443,6 +472,7 @@ CppTL::BatchAllocator<EnumTypeDecl> enumTypeDeclAlloc_; CppTL::BatchAllocator<EnumValueDecl> enumValueAlloc_; CppTL::BatchAllocator<ClassDecl> classDeclAlloc_; + CppTL::BatchAllocator<SymbolDecl> symbolDeclAlloc_; //CppTL::BatchAllocator<UnknownScope> unknownScopeAlloc_; Type *builtIns_[ (1 << signBitSize) * typeMaxCount ]; }; Modified: rfta/trunk/include/rfta/forwards.h =================================================================== --- rfta/trunk/include/rfta/forwards.h 2007-04-24 06:49:08 UTC (rev 25) +++ rfta/trunk/include/rfta/forwards.h 2007-04-25 22:05:39 UTC (rev 26) @@ -28,6 +28,7 @@ class NamespaceScope; class Scope; class ScopeVisitor; +class SymbolDecl; class Type; class TypeDeclaration; Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-24 06:49:08 UTC (rev 25) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-25 22:05:39 UTC (rev 26) @@ -162,8 +162,8 @@ type_specifier ( ';' | ( => declarationTypeIsSelfType[] fn_suffix ( ';' | fn_definition ) ) - | ( init_declarator ( ?initializer *( ',' init_declarator ?initializer) ';' - | fn_definition + | ( init_declarator ( fn_definition + | ?initializer *( ',' init_declarator ?initializer) ';' ) ) ) @@ -174,7 +174,7 @@ | simple_type_specifier ) *fn_suffix | '~' identifier '(' ')' #destructor - | identifier *fn_suffix + | $idVar=(identifier) ?fn_suffix !setDeclarator[$idVar] ) ::ptr_operator # ignore pointer to member Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-24 06:49:08 UTC (rev 25) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-25 22:05:39 UTC (rev 26) @@ -30,6 +30,7 @@ , currentClassDecl_( 0 ) , typeIdScope_( 0 ) , typeId_( 0 ) + , isSelfType_( false ) { namespaceScopes_.push( &declManager.getGlobalNamespaceScope() ); accessLevels_.push( accessPublic ); @@ -76,6 +77,7 @@ else currentEnumDecl_ = &( decls_.declareEnum( *(id.start_), currentScope ) ); typeId_ = currentEnumDecl_; + isSelfType_ = false; } @@ -166,6 +168,7 @@ void CxxParserAction::exitClassDeclaration() { + isSelfType_ = false; typeId_ = classScopes_.top(); accessLevels_.pop(); classScopes_.pop(); @@ -236,16 +239,26 @@ void CxxParserAction::endTypeId(const TokenScannerPosRange &typeId) { - if ( typeIdQualifiedLookUp_ ) - typeId_ = &( decls_.declareOrResolveQualifiedType( *(typeId.start_), *typeIdScope_ ) ); + if ( typeIdScope_->isSelfTypeId( typeId.start_->text_ ) ) + { + isSelfType_ = true; + typeId_ = 0; + } else - typeId_ = &( decls_.declareOrResolveUnqualifiedType( *(typeId.start_), *typeIdScope_ ) ); + { + isSelfType_ = false; + if ( typeIdQualifiedLookUp_ ) + typeId_ = &( decls_.declareOrResolveQualifiedType( *(typeId.start_), *typeIdScope_ ) ); + else + typeId_ = &( decls_.declareOrResolveUnqualifiedType( *(typeId.start_), *typeIdScope_ ) ); + } } void CxxParserAction::setBuiltInsTypeSpecifier(const TokenScannerPosRange &builtins) { + isSelfType_ = false; BuiltInKind type = typeInt; BuiltInSign sign = signUnspecified; for ( TokenScannerPos current = builtins.start_; current != builtins.end_; ++current ) @@ -340,6 +353,16 @@ void +CxxParserAction::setDeclarator(const TokenScannerPosRange &idVar) +{ + if ( isSelfType_ ) + typeId_ = CppTL::checkedCast( typeIdScope_, CppTL::Type<Type *>() ); + CPPTL_ASSERT_MESSAGE( typeId_ != 0, "Invalid typeId_" ); + decls_.declareSymbol( *(idVar.start_), *typeId_, getCurrentScope() ); +} + + +void CxxParserAction::handleDeclarationError(const TokenScannerPosRange &tokens) { addError( tokens, "Error in declaration" ); @@ -378,9 +401,11 @@ bool CxxParserAction::declarationTypeIsSelfType() { - if ( classScopes_.empty() ) - return false; - return typeId_ == classScopes_.top(); + return isSelfType_; + + //if ( classScopes_.empty() ) + // return false; + //return typeId_ == classScopes_.top(); } } // namespace Rfta { Modified: rfta/trunk/src/lib_rftaparser/cxxtype.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-24 06:49:08 UTC (rev 25) +++ rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-25 22:05:39 UTC (rev 26) @@ -57,6 +57,13 @@ } +bool +Scope::isSelfTypeId( TextId id ) const +{ + return false; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class NamespaceScope @@ -586,9 +593,50 @@ } +bool +ClassDecl::isSelfTypeId( TextId id ) const +{ + return id == id_.text_; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +// class SymbolDecl +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +SymbolDecl::SymbolDecl( const LocatedSymbol &id, + Type &type ) + : id_( id ) + , type_( type ) +{ +} + +void +SymbolDecl::accept( DeclarationVisitor &visitor ) +{ + visitor.visitSymbolDecl( *this ); +} + + +const LocatedSymbol & +SymbolDecl::getDeclSymbol() const +{ + return id_; +} + + +Type & +SymbolDecl::getDeclType() const +{ + return type_; +} + + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// // class BuiltInType // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -855,4 +903,16 @@ } +SymbolDecl & +DeclarationManager::declareSymbol( const LocatedSymbol &id, + Type &type, + Scope &scope ) +{ + SymbolDecl *symbolDecl = + new (symbolDeclAlloc_.allocate()) SymbolDecl( id, type ); + scope.addNamedDeclaration( id.text_, *symbolDecl ); + return *symbolDecl; +} + + } // namespace Rfta { Modified: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp 2007-04-24 06:49:08 UTC (rev 25) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-25 22:05:39 UTC (rev 26) @@ -190,24 +190,32 @@ while ( enumValues.hasNext() ) { Rfta::EnumValueDecl *enumValueDecl = enumValues.next(); - fprintf( fout_, "%svalue: %s\n", indent_.c_str(), getSymbolText(enumValueDecl->getSymbol()).c_str() ); + printLine( "value: %s", getSymbolText(enumValueDecl->getSymbol()).c_str() ); } printScopeFooter(); } virtual void visitEnumValueDecl( Rfta::EnumValueDecl &enumValueDecl ) { - fprintf( fout_, "%senum value: %s\n", indent_.c_str(), getSymbolText(enumValueDecl.getSymbol()).c_str() ); + printLine( "enum value: %s", getSymbolText(enumValueDecl.getSymbol()).c_str() ); } virtual void visitClassDecl( Rfta::ClassDecl &classDecl ) { if ( classDecl.hasSymbol() ) - fprintf( fout_, "%sclass: %s\n", indent_.c_str(), getSymbolText(classDecl.getSymbol()).c_str() ); + printLine( "class: %s", getSymbolText(classDecl.getSymbol()).c_str() ); else - fprintf( fout_, "%sclass <anonymous>\n", indent_.c_str() ); + printLine( "class: <anonymous>" ); } + virtual void visitSymbolDecl( Rfta::SymbolDecl &symbolDecl ) + { + CppTL::ConstString type = getQualifiedTypeId( symbolDecl.getDeclType() ); + printLine( "symbol: %s of type %s", + getSymbolText(symbolDecl.getDeclSymbol()).c_str(), + type.c_str() ); + } + private: CppTL::ConstString getSymbolText( const Rfta::LocatedSymbol &symbol ) const { @@ -219,29 +227,42 @@ return contentManager_.getSymbolText(text); } - CppTL::ConstString getQualifiedTypeId( const Rfta::TypeDeclaration &type ) const + CppTL::ConstString getQualifiedTypeId( Rfta::Type &type ) const { - CppTL::ConstString typeName = getSymbolText( type.getSymbol() ); - Rfta::Scope *scope = &( type.getDeclarationScope() ); - while ( scope ) + Rfta::TypeDeclaration *typeDecl = type.isTypeDeclaration(); + if ( typeDecl != 0 ) { - if ( dynamic_cast<Rfta::GlobalNamespaceScope *>( scope ) ) + CppTL::ConstString typeName = getSymbolText( typeDecl->getSymbol() ); + Rfta::Scope *scope = &( typeDecl->getDeclarationScope() ); + while ( scope ) { - typeName = "::" + typeName; - break; + if ( dynamic_cast<Rfta::GlobalNamespaceScope *>( scope ) ) + { + typeName = "::" + typeName; + break; + } + else if ( dynamic_cast<Rfta::AnonymousNamespaceScope *>( scope ) ) + { + typeName = "<anonymous>::"; + break; + } + else // class + { + typeName = getText( scope->getScopeSymbol() ) + "::" + typeName; + scope = scope->getOutterScope(); + } } - else if ( dynamic_cast<Rfta::AnonymousNamespaceScope *>( scope ) ) - { - typeName = "<anonymous>::"; - break; - } - else // class - { - typeName = getText( scope->getScopeSymbol() ) + "::" + typeName; - scope = scope->getOutterScope(); - } + return typeName; } - return typeName; + else if ( type.isBuiltIn() ) + { + Rfta::BuiltInType *builtInType = type.isBuiltIn(); + return builtInType->toString(); + } + else + { + return "<type unsupported by dumper>"; + } } void printScopeHeader( const std::string &type, const std::string &name ) @@ -275,7 +296,6 @@ }; - int __cdecl main( int argc, const char *argv[] ) { std::string log; Added: rfta/trunk/testdata/cxxparser_ut/t_class_008_self_pointer.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_008_self_pointer.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_008_self_pointer.cpp 2007-04-25 22:05:39 UTC (rev 26) @@ -0,0 +1,4 @@ +class C0008 +{ + C0008 *self_; +}; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-24 06:49:09
|
Revision: 25 http://rfta.svn.sourceforge.net/rfta/?rev=25&view=rev Author: blep Date: 2007-04-23 23:49:08 -0700 (Mon, 23 Apr 2007) Log Message: ----------- - added support for in class constructor declaration. - rough support for built-in types. Modified Paths: -------------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/include/rfta/cxxtype.h rfta/trunk/include/rfta/forwards.h rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/src/lib_rftaparser/cxxtype.cpp Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_007_ctor.cpp Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-22 14:40:15 UTC (rev 24) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-24 06:49:08 UTC (rev 25) @@ -55,12 +55,16 @@ virtual void beginTypeId(const TokenScannerPosRange &gscope); virtual void addTypeIdScope(const TokenScannerPosRange &scope); virtual void endTypeId(const TokenScannerPosRange &typeId); + virtual void setBuiltInsTypeSpecifier(const TokenScannerPosRange &builtins); + virtual void setTypeSpecifier(const TokenScannerPosRange &cv1, const TokenScannerPosRange &cv2); virtual bool declarationTypeIsSelfType(); private: void addError( const TokenScannerPosRange &tokens, const char *message ); + void updateCVQualifier( const TokenScannerPosRange &cv1, + CVQualifier &qualifiers ); Scope &getCurrentScope(); @@ -74,7 +78,12 @@ LocatedSymbol className_; ClassDecl *currentClassDecl_; Scope *typeIdScope_; - TypeDeclaration *typeId_; + /// typeId_ will be set on the following events: + /// - Beginning enum declaration + /// - Exiting class declaration + /// - Ending a (scoped) type identifier + Type *typeId_; + unsigned int typeSpecifierQualifier_; bool typeIdQualifiedLookUp_; //ScopeManager scopeManager_; }; Modified: rfta/trunk/include/rfta/cxxtype.h =================================================================== --- rfta/trunk/include/rfta/cxxtype.h 2007-04-22 14:40:15 UTC (rev 24) +++ rfta/trunk/include/rfta/cxxtype.h 2007-04-24 06:49:08 UTC (rev 25) @@ -15,6 +15,20 @@ * use a linear search. */ +/* + Base type are of the following kinds: + - BuiltIn + - Class + - Enum + - Function + - Typedef + + Type decorator are of the following kinds: + - const/volatile + - array + - pointer/reference + */ + namespace Rfta { enum AccessLevel // bit field @@ -33,7 +47,45 @@ classKeyUnion }; +enum CVQualifier +{ + cvQualifierNone = 0, + cvQualifierConst = 1, + cvQualifierVolatile = 2 +}; + +enum BuiltInKind +{ + typeVoid = 0, + typeChar, + typeWChar, + typeInt, + typeShortInt, + typeLongInt, + typeLongLong, + typeFloat, + typeDouble, + typeLongDouble, + typeBool, + typeMsExtInt8, + typeMsExtInt16, + typeMsExtInt32, + typeMsExtInt64, + typeMaxCount, + typeBitSize = 5 +}; + +enum BuiltInSign +{ + signUnspecified = 0, + signSigned, + signUnsigned, + signMaxCount, + signBitSize = 2 +}; + + class ScopeVisitor { public: @@ -65,6 +117,7 @@ virtual Scope *getOutterScope() const = 0; virtual TextId getScopeSymbol() const = 0; virtual TypeDeclaration *resolveQualifiedType( TextId id ) const = 0; + TypeDeclaration *resolveUnqualifiedType( TextId id ) const; private: Scope( const Scope &other ); @@ -173,18 +226,37 @@ }; +class Type +{ +public: + virtual ~Type(); + + virtual BuiltInType *isBuiltIn() = 0; + + virtual TypeDeclaration *isTypeDeclaration() = 0; + + virtual TextId getUnqualifiedTypeName() const = 0; +}; + + class TypeDeclaration : public Declaration + , public Type { public: bool hasSymbol() const; - TextId getTypeSymbol() const; - const Location &getLocation() const; virtual const LocatedSymbol &getSymbol() const = 0; virtual Scope &getDeclarationScope() const = 0; + +public: // overridden from Type + virtual BuiltInType *isBuiltIn(); + + virtual TypeDeclaration *isTypeDeclaration(); + + virtual TextId getUnqualifiedTypeName() const; }; typedef CppTL::AnyEnumerator<EnumValueDecl *> EnumEnumValueDecl; @@ -302,9 +374,35 @@ }; +class BuiltInType : public Type +{ +public: + BuiltInType( BuiltInKind type, BuiltInSign sign ); + + CppTL::ConstString toString() const; + +public: // overridden from Type + virtual BuiltInType *isBuiltIn(); + + virtual TypeDeclaration *isTypeDeclaration(); + + virtual TextId getUnqualifiedTypeName() const; + +private: + BuiltInType( const BuiltInType &other ); + BuiltInType &operator =( const BuiltInType &other ); + + BuiltInKind type_; + BuiltInSign sign_; +}; + + + class DeclarationManager { public: + DeclarationManager(); + GlobalNamespaceScope &getGlobalNamespaceScope(); NamespaceScope &declareNamespace( const LocatedSymbol &id, NamespaceScope &scope ); @@ -327,17 +425,26 @@ Scope &scope ); Scope &declareUnknownScope( const LocatedSymbol &id, Scope &scope ); - TypeDeclaration &declareOrResolveType( const LocatedSymbol &id, - Scope &scope ); + TypeDeclaration &declareOrResolveQualifiedType( const LocatedSymbol &id, + Scope &scope ); + + TypeDeclaration &declareOrResolveUnqualifiedType( const LocatedSymbol &id, + Scope &scope ); TypeDeclaration &declareUnknownType( const LocatedSymbol &id, Scope &scope ); + Type &getBuildInType( BuiltInSign sign, BuiltInKind type ); + private: + void initializeBuiltIns(); + void setBuiltIn( BuiltInKind type, BuiltInSign sign, Type &builtinType ); + GlobalNamespaceScope globalNamespace_; CppTL::BatchAllocator<NamespaceDecl> namespaceDeclAlloc_; CppTL::BatchAllocator<EnumTypeDecl> enumTypeDeclAlloc_; CppTL::BatchAllocator<EnumValueDecl> enumValueAlloc_; CppTL::BatchAllocator<ClassDecl> classDeclAlloc_; //CppTL::BatchAllocator<UnknownScope> unknownScopeAlloc_; + Type *builtIns_[ (1 << signBitSize) * typeMaxCount ]; }; Modified: rfta/trunk/include/rfta/forwards.h =================================================================== --- rfta/trunk/include/rfta/forwards.h 2007-04-22 14:40:15 UTC (rev 24) +++ rfta/trunk/include/rfta/forwards.h 2007-04-24 06:49:08 UTC (rev 25) @@ -16,6 +16,7 @@ // cxxtype.h class AnonymousNamespaceScope; +class BuiltInType; class ClassDecl; class Declaration; class DeclarationManager; @@ -27,6 +28,7 @@ class NamespaceScope; class Scope; class ScopeVisitor; +class Type; class TypeDeclaration; inline TextId nullTextId() { Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-22 14:40:15 UTC (rev 24) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-24 06:49:08 UTC (rev 25) @@ -205,23 +205,21 @@ | 'virtual' | 'explicit') ) -::simple_typeid - fundamental_type - | ?'::' identifier *( '::' identifier ) - # type specifier used for conversion operator ::simple_type_specifier ?($cv1=(cv_qualifier_seq)) - simple_typeid + ( fundamental_type | type_id ) ?($cv2=(cv_qualifier_seq)) *ptr_operator +# result of this expression is used by predicate declarationTypeIsSelfType[] ::type_specifier - ?($cv1=(cv_qualifier_seq)) - ( simple_typeid + $cv1=(?(cv_qualifier_seq)) + ( fundamental_type + | type_id | class_specifier | enum_specifier - ) ?($cv2=(cv_qualifier_seq)) + ) $cv2=(?(cv_qualifier_seq)) !setTypeSpecifier[$cv1, $cv2] ::cv_qualifier_seq +( 'const' | 'volatile' ) @@ -245,6 +243,7 @@ | '__int64' ) ) + !setBuiltInsTypeSpecifier[ $builtins ] ::operator '+' | '-' | '*' | '/' | '%' Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-22 14:40:15 UTC (rev 24) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-24 06:49:08 UTC (rev 25) @@ -75,6 +75,7 @@ currentScope ) ); else currentEnumDecl_ = &( decls_.declareEnum( *(id.start_), currentScope ) ); + typeId_ = currentEnumDecl_; } @@ -146,7 +147,9 @@ CPPTL_DEBUG_ASSERT_UNREACHABLE; } } - currentClassDecl_->addBaseClass( *typeId_, AccessLevel( access ) ); + TypeDeclaration *typeDecl = typeId_->isTypeDeclaration(); + CPPTL_ASSERT_MESSAGE( typeDecl != 0, "Inherited type is not an aggregate." ); + currentClassDecl_->addBaseClass( *typeDecl, AccessLevel( access ) ); } @@ -163,6 +166,7 @@ void CxxParserAction::exitClassDeclaration() { + typeId_ = classScopes_.top(); accessLevels_.pop(); classScopes_.pop(); } @@ -232,11 +236,110 @@ void CxxParserAction::endTypeId(const TokenScannerPosRange &typeId) { - typeId_ = &( decls_.declareOrResolveType( *(typeId.start_), *typeIdScope_ ) ); + if ( typeIdQualifiedLookUp_ ) + typeId_ = &( decls_.declareOrResolveQualifiedType( *(typeId.start_), *typeIdScope_ ) ); + else + typeId_ = &( decls_.declareOrResolveUnqualifiedType( *(typeId.start_), *typeIdScope_ ) ); } void +CxxParserAction::setBuiltInsTypeSpecifier(const TokenScannerPosRange &builtins) +{ + BuiltInKind type = typeInt; + BuiltInSign sign = signUnspecified; + for ( TokenScannerPos current = builtins.start_; current != builtins.end_; ++current ) + { + switch ( current->tokenId_ ) + { + case T_SHORT: + type = typeShortInt; + break; + case T_LONG: + type = ( type == typeLongInt ) ? typeLongLong : typeLongInt; + break; + case T_UNSIGNED: + sign = (sign == signUnspecified) ? signUnsigned : sign; + break; + case T_SIGNED: + sign = (sign == signUnspecified) ? signSigned : sign; + break; + case T_BOOL: + type = typeBool; + break; + case T_FLOAT: + type = typeFloat; + break; + case T_DOUBLE: + type = (type == typeLongInt) ? typeLongDouble : typeDouble; + break; + case T_VOID: + type = typeVoid; + break; + case T_CHAR: + type = typeChar; + break; + case T_WCHART: + type = typeWChar; + break; + case T_INT: + type = (type == typeVoid) ? typeInt : type; + break; + case T_MSEXT_INT8: + type = typeMsExtInt8; + break; + case T_MSEXT_INT16: + type = typeMsExtInt16; + break; + case T_MSEXT_INT32: + type = typeMsExtInt32; + break; + case T_MSEXT_INT64: + type = typeMsExtInt64; + break; + default: + CPPTL_DEBUG_ASSERT_UNREACHABLE; + } + } + typeId_ = &( decls_.getBuildInType( sign, type ) ); +} + + +void +CxxParserAction::setTypeSpecifier(const TokenScannerPosRange &cv1, + const TokenScannerPosRange &cv2) +{ + CVQualifier qualifiers = cvQualifierNone; + updateCVQualifier( cv1, qualifiers ); + updateCVQualifier( cv2, qualifiers ); + // @todo create decorator for typeId_ +} + + +void +CxxParserAction::updateCVQualifier( const TokenScannerPosRange &cv1, + CVQualifier &qualifiers ) +{ + unsigned int qualifier = 0; + for ( TokenScannerPos pos = cv1.start_; pos != cv1.end_; ++pos ) + { + switch ( pos->tokenId_ ) + { + case T_CONST: + qualifier |= cvQualifierConst; + break; + case T_VOLATILE: + qualifier |= cvQualifierVolatile; + break; + default: + CPPTL_DEBUG_ASSERT_UNREACHABLE; + } + } + qualifiers = CVQualifier( qualifiers | qualifier ); +} + + +void CxxParserAction::handleDeclarationError(const TokenScannerPosRange &tokens) { addError( tokens, "Error in declaration" ); @@ -275,7 +378,9 @@ bool CxxParserAction::declarationTypeIsSelfType() { - return false; // @todo implement this + if ( classScopes_.empty() ) + return false; + return typeId_ == classScopes_.top(); } } // namespace Rfta { Modified: rfta/trunk/src/lib_rftaparser/cxxtype.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-22 14:40:15 UTC (rev 24) +++ rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-24 06:49:08 UTC (rev 25) @@ -38,6 +38,25 @@ } +TypeDeclaration * +Scope::resolveUnqualifiedType( TextId id ) const +{ + TypeDeclaration *typeDecl = resolveQualifiedType( id ); + if ( typeDecl == 0 ) + { + for ( Scope *outterScope = getOutterScope(); + outterScope != 0; + outterScope = outterScope->getOutterScope() ) + { + typeDecl = outterScope->resolveQualifiedType( id ); + if ( typeDecl != 0 ) + break; + } + } + return typeDecl; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class NamespaceScope @@ -242,6 +261,17 @@ // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +// class Type +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +Type::~Type() +{ +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// // class TypeDeclaration // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -253,20 +283,34 @@ } -TextId -TypeDeclaration::getTypeSymbol() const +const Location & +TypeDeclaration::getLocation() const { - return getSymbol().text_; + return getSymbol(); } -const Location & -TypeDeclaration::getLocation() const +BuiltInType * +TypeDeclaration::isBuiltIn() { - return getSymbol(); + return 0; } +TypeDeclaration * +TypeDeclaration::isTypeDeclaration() +{ + return this; +} + + +TextId +TypeDeclaration::getUnqualifiedTypeName() const +{ + return getSymbol().text_; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class EnumTypeDecl @@ -542,12 +586,70 @@ } + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +// class BuiltInType +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +BuiltInType::BuiltInType( BuiltInKind type, BuiltInSign sign ) + : type_( type ) + , sign_( sign ) +{ +} + + +BuiltInType * +BuiltInType::isBuiltIn() +{ + return this; +} + + +TypeDeclaration * +BuiltInType::isTypeDeclaration() +{ + return 0; +} + + +TextId +BuiltInType::getUnqualifiedTypeName() const +{ + return nullTextId(); +} + + +CppTL::ConstString +BuiltInType::toString() const +{ + static const char *builtInText[typeMaxCount] = { + "void", "char", "wchar_t", "int", "short int", + "long int", "long long", "float", "double", "long double", "bool", + "__int8", "__int16", "__int32", "__int64" + }; + const char *signText = ""; + if ( sign_ == signSigned ) + signText = "signed "; + else if ( sign_ == signUnsigned ) + signText = "unsigned "; + return CppTL::StringConcatenator( signText, builtInText[type_] ); +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// // class DeclarationManager // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +DeclarationManager::DeclarationManager() +{ + initializeBuiltIns(); +} + + GlobalNamespaceScope & DeclarationManager::getGlobalNamespaceScope() { @@ -658,9 +760,10 @@ return declareNamedClass( classKeyClass, id, scope, accessPublic ); } + TypeDeclaration & -DeclarationManager::declareOrResolveType( const LocatedSymbol &id, - Scope &scope ) +DeclarationManager::declareOrResolveQualifiedType( const LocatedSymbol &id, + Scope &scope ) { TypeDeclaration *resolvedType = scope.resolveQualifiedType( id.text_ ); if ( resolvedType == 0 ) @@ -670,6 +773,17 @@ TypeDeclaration & +DeclarationManager::declareOrResolveUnqualifiedType( const LocatedSymbol &id, + Scope &scope ) +{ + TypeDeclaration *resolvedType = scope.resolveUnqualifiedType( id.text_ ); + if ( resolvedType == 0 ) + resolvedType = &( declareUnknownType( id, scope ) ); + return *resolvedType; +} + + +TypeDeclaration & DeclarationManager::declareUnknownType( const LocatedSymbol &id, Scope &scope ) { // dummy implementation @@ -677,4 +791,68 @@ } +Type & +DeclarationManager::getBuildInType( BuiltInSign sign, BuiltInKind type ) +{ + unsigned int index = ((unsigned int)type) << signBitSize | (unsigned int)sign; + CPPTL_ASSERT_MESSAGE( builtIns_[ index ] != 0, "Attempting to use invalid type." ); + return *( builtIns_[ index ] ); +} + +void +DeclarationManager::initializeBuiltIns() +{ + memset( builtIns_, 0, sizeof(builtIns_) ); + +#define RFTA_CXXTYPE_DECLARE_AND_SET_BUILTIN( builtInType ) \ + static BuiltInType decltype##builtInType( builtInType, signUnspecified ); \ + setBuiltIn( builtInType, signUnspecified, decltype##builtInType ); \ + setBuiltIn( builtInType, signSigned, decltype##builtInType ); \ + setBuiltIn( builtInType, signUnsigned, decltype##builtInType ) + + // same registration for signed/unsigned (?may be should report error) + RFTA_CXXTYPE_DECLARE_AND_SET_BUILTIN( typeVoid ); + RFTA_CXXTYPE_DECLARE_AND_SET_BUILTIN( typeFloat ); + RFTA_CXXTYPE_DECLARE_AND_SET_BUILTIN( typeDouble ); + RFTA_CXXTYPE_DECLARE_AND_SET_BUILTIN( typeLongDouble ); + RFTA_CXXTYPE_DECLARE_AND_SET_BUILTIN( typeBool ); + + // different type for signed/unsigned +#define RFTA_CXXTYPE_DECLARE_DISTINCT_BUILTIN( builtInType, builtInSign ) \ + static BuiltInType decltype##builtInType##builtInSign( builtInType, builtInSign ); \ + setBuiltIn( builtInType, builtInSign, decltype##builtInType##builtInSign ) + + RFTA_CXXTYPE_DECLARE_DISTINCT_BUILTIN( typeChar, signUnspecified ); + RFTA_CXXTYPE_DECLARE_DISTINCT_BUILTIN( typeChar, signSigned ); + RFTA_CXXTYPE_DECLARE_DISTINCT_BUILTIN( typeChar, signUnsigned ); + + RFTA_CXXTYPE_DECLARE_DISTINCT_BUILTIN( typeWChar, signUnspecified ); + RFTA_CXXTYPE_DECLARE_DISTINCT_BUILTIN( typeWChar, signSigned ); + RFTA_CXXTYPE_DECLARE_DISTINCT_BUILTIN( typeWChar, signUnsigned ); + + // unspecified is signed +#define RFTA_CXXTYPE_DECLARE_INTEGER_BUILTIN( builtInType ) \ + RFTA_CXXTYPE_DECLARE_DISTINCT_BUILTIN( builtInType, signSigned ); \ + setBuiltIn( builtInType, signUnspecified, decltype##builtInType##signSigned ); \ + RFTA_CXXTYPE_DECLARE_DISTINCT_BUILTIN( builtInType, signUnsigned ) \ + + RFTA_CXXTYPE_DECLARE_INTEGER_BUILTIN(typeInt); + RFTA_CXXTYPE_DECLARE_INTEGER_BUILTIN(typeShortInt); + RFTA_CXXTYPE_DECLARE_INTEGER_BUILTIN(typeLongInt); + RFTA_CXXTYPE_DECLARE_INTEGER_BUILTIN(typeLongLong); + RFTA_CXXTYPE_DECLARE_INTEGER_BUILTIN(typeMsExtInt8); + RFTA_CXXTYPE_DECLARE_INTEGER_BUILTIN(typeMsExtInt16); + RFTA_CXXTYPE_DECLARE_INTEGER_BUILTIN(typeMsExtInt32); + RFTA_CXXTYPE_DECLARE_INTEGER_BUILTIN(typeMsExtInt64); +} + + +void +DeclarationManager::setBuiltIn( BuiltInKind type, BuiltInSign sign, Type &builtinType ) +{ + unsigned int index = ((unsigned int)type) << signBitSize | (unsigned int)sign; + builtIns_[ index ] = &builtinType; +} + + } // namespace Rfta { Added: rfta/trunk/testdata/cxxparser_ut/t_class_007_ctor.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_007_ctor.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_007_ctor.cpp 2007-04-24 06:49:08 UTC (rev 25) @@ -0,0 +1,15 @@ +class Class007A +{ +public: + Class007A(); + Class007A( int x, int y ); +}; + +Class007A::Class007A() +{ +} + + +Class007A::Class007A( int x, int y ) +{ +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-22 14:40:16
|
Revision: 24 http://rfta.svn.sourceforge.net/rfta/?rev=24&view=rev Author: blep Date: 2007-04-22 07:40:15 -0700 (Sun, 22 Apr 2007) Log Message: ----------- - fixed nested scope look-up in type_id. Modified Paths: -------------- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance_ns.cpp rfta/trunk/testdata/cxxparser_ut/t_class_006_inheritance_ns.cpp rfta/trunk/testdata/cxxparser_ut/t_guess_001_inheritance.cpp Removed Paths: ------------- rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance3.cpp Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-22 14:22:01 UTC (rev 23) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-22 14:40:15 UTC (rev 24) @@ -218,12 +218,12 @@ if ( typeIdQualifiedLookUp_ ) { typeIdScope_ = &( decls_.declareOrResolveQualifiedScope( *(scope.start_), - getCurrentScope() ) ); + *typeIdScope_ ) ); } else { typeIdScope_ = &( decls_.declareOrResolveUnqualifiedScope( *(scope.start_), - getCurrentScope() ) ); + *typeIdScope_ ) ); typeIdQualifiedLookUp_ = true; } } Deleted: rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance3.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance3.cpp 2007-04-22 14:22:01 UTC (rev 23) +++ rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance3.cpp 2007-04-22 14:40:15 UTC (rev 24) @@ -1,3 +0,0 @@ -class Struct005 : public std::exception -{ -}; \ No newline at end of file Added: rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance_ns.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance_ns.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance_ns.cpp 2007-04-22 14:40:15 UTC (rev 24) @@ -0,0 +1,10 @@ +namespace C5 { + class Class005A + { + public: + }; +} + +class Class005B : public C5::Class005A +{ +}; \ No newline at end of file Added: rfta/trunk/testdata/cxxparser_ut/t_class_006_inheritance_ns.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_006_inheritance_ns.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_006_inheritance_ns.cpp 2007-04-22 14:40:15 UTC (rev 24) @@ -0,0 +1,16 @@ +namespace C6A { + namespace C6AA { + class Class006A + { + public: + }; + } +} + +namespace C6B { + + class Class006B : public C6A::C6AA::Class006A + { + }; + +} \ No newline at end of file Copied: rfta/trunk/testdata/cxxparser_ut/t_guess_001_inheritance.cpp (from rev 23, rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance3.cpp) =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_guess_001_inheritance.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_guess_001_inheritance.cpp 2007-04-22 14:40:15 UTC (rev 24) @@ -0,0 +1,3 @@ +class Struct005 : public std::exception +{ +}; \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-22 14:22:31
|
Revision: 23 http://rfta.svn.sourceforge.net/rfta/?rev=23&view=rev Author: blep Date: 2007-04-22 07:22:01 -0700 (Sun, 22 Apr 2007) Log Message: ----------- - started adding scoped type support. Currently only for based class and bugged (look-up of existing namespace fails). Modified Paths: -------------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/include/rfta/cxxparserbase.h rfta/trunk/include/rfta/cxxtype.h rfta/trunk/include/rfta/token.h rfta/trunk/makefiles/vs8/test_rftaparser.vcproj rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/src/lib_rftaparser/cxxtype.cpp rfta/trunk/src/test_rftaparser/main.cpp Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_004_inheritance2.cpp rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance3.cpp rfta/trunk/testdata/cxxparser_ut/t_decl_005_function.cpp Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-20 07:29:43 UTC (rev 22) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-22 14:22:01 UTC (rev 23) @@ -31,18 +31,31 @@ EnumErrorInfo enumErrors() const; public: // overridden from CxxParserDelegate + // namespace virtual void declareAndEnterNamespace(const TokenScannerPosRange &id); virtual void exitNamespaceDeclaration(); + + // enum virtual void declareAndEnterEnum(const TokenScannerPosRange &id, const TokenScannerPosRange &enumStart); virtual void declareEnumValue(const TokenScannerPosRange &id); + + // error virtual void handleDeclarationError(const TokenScannerPosRange &error_tokens); virtual void handleStatementError(const TokenScannerPosRange &error_tokens); + + // class virtual void declareClass(const TokenScannerPosRange &ck, const TokenScannerPosRange &name); - virtual void addBaseClassToClassDeclaration(const TokenScannerPosRange &qualifiers, const TokenScannerPosRange &id); + virtual void addBaseClassToClassDeclaration(const TokenScannerPosRange &qualifiers); virtual void enterClassDeclaration(); virtual void exitClassDeclaration(); virtual void setClassName(const TokenScannerPosRange &id); virtual void setMemberVisibility(const TokenScannerPosRange &access); + + // type id + virtual void beginTypeId(const TokenScannerPosRange &gscope); + virtual void addTypeIdScope(const TokenScannerPosRange &scope); + virtual void endTypeId(const TokenScannerPosRange &typeId); + virtual bool declarationTypeIsSelfType(); private: @@ -60,6 +73,9 @@ TokenContentManager &contentManager_; LocatedSymbol className_; ClassDecl *currentClassDecl_; + Scope *typeIdScope_; + TypeDeclaration *typeId_; + bool typeIdQualifiedLookUp_; //ScopeManager scopeManager_; }; Modified: rfta/trunk/include/rfta/cxxparserbase.h =================================================================== --- rfta/trunk/include/rfta/cxxparserbase.h 2007-04-20 07:29:43 UTC (rev 22) +++ rfta/trunk/include/rfta/cxxparserbase.h 2007-04-22 14:22:01 UTC (rev 23) @@ -3,6 +3,7 @@ # include "forwards.h" # include "token.h" +# include <stdio.h> # include <cpptl/conststring.h> # include <vector> # include <assert.h> @@ -45,6 +46,7 @@ , traceEnabled_( false ) , repository_( 0 ) { + setLogFile(0); } // notes: tokens is garbage after call. @@ -55,10 +57,12 @@ end_ = &tokens_.at(0) + tokens_.size(); } - void enableTrace( TokenContentManager &repository ) + void enableTrace( TokenContentManager &repository, + FILE *logFile ) { repository_ = &repository; traceEnabled_ = true; + setLogFile( logFile ); } inline bool match( TokenId id ) @@ -100,7 +104,9 @@ { CppTL::StringBuffer tokensText; dumpTokens( tokensText ); - printf( "%s=> %s: %s\n", indent_.c_str(), name, tokensText.c_str() ); + fprintf( logFile_, + "%s=> %s: %s\n", + indent_.c_str(), name, tokensText.c_str() ); indent_ += " "; } } @@ -114,8 +120,9 @@ char matchedLetter = matched ? '=' : '#'; CppTL::StringBuffer tokensText; dumpTokens( tokensText ); - printf( "%s<%c %s: %s\n", - indent_.c_str(), matchedLetter, name, tokensText.c_str() ); + fprintf( logFile_, + "%s<%c %s: %s\n", + indent_.c_str(), matchedLetter, name, tokensText.c_str() ); } return matched; } @@ -153,7 +160,8 @@ appendTokenRangeText( buffer, *it ); buffer += " ]]"; } - printf( "%s%s %s %s\n", + fprintf( logFile_, + "%s%s %s %s\n", indent_.c_str(), prefix, name, buffer.c_str() ); } @@ -190,6 +198,14 @@ appendTokenText( buffer, token ); } } + + void setLogFile( FILE *logFile ) + { + if ( !logFile ) + logFile_ = stdout; + else + logFile_ = logFile; + } private: Tokens tokens_; @@ -198,6 +214,7 @@ CppTL::ConstString indent_; TokenContentManager *repository_; // only available for trace bool traceEnabled_; + FILE *logFile_; }; } // namespace Rfta { Modified: rfta/trunk/include/rfta/cxxtype.h =================================================================== --- rfta/trunk/include/rfta/cxxtype.h 2007-04-20 07:29:43 UTC (rev 22) +++ rfta/trunk/include/rfta/cxxtype.h 2007-04-22 14:22:01 UTC (rev 23) @@ -11,16 +11,21 @@ # include <stack> # include <vector> +/** @todo Revisite type and scope resolution. Current implementation + * use a linear search. + */ + namespace Rfta { -enum AccessLevel +enum AccessLevel // bit field { - accessPublic = 1, - accessProtected, - accessPrivate + accessPublic = 1, + accessProtected = 2, + accessPrivate = 4, + accessVisibility = (accessPublic | accessProtected | accessPrivate ), + accessVirtual = 8 }; - enum ClassKey { classKeyClass = 1, @@ -55,6 +60,12 @@ virtual void accept( ScopeVisitor &visitor ) = 0; + virtual Scope *resolveQualifiedScope( TextId id )= 0; + Scope *resolveUnqualifiedScope( TextId id ); + virtual Scope *getOutterScope() const = 0; + virtual TextId getScopeSymbol() const = 0; + virtual TypeDeclaration *resolveQualifiedType( TextId id ) const = 0; + private: Scope( const Scope &other ); Scope &operator =( const Scope &other ); @@ -76,6 +87,8 @@ virtual Scope *isScope(); + virtual TypeDeclaration *isNamedType( TextId id ); + private: Declaration( const Declaration &other ); Declaration &operator =( const Declaration &other ); @@ -101,6 +114,9 @@ virtual void addNamedDeclaration( TextId id, Declaration &typeDecl ); virtual void addAnonymousDeclaration( Declaration &typeDecl ); virtual void addScope( Scope &scope ); + virtual Scope *resolveQualifiedScope( TextId id ); + virtual TextId getScopeSymbol() const; + virtual TypeDeclaration *resolveQualifiedType( TextId id ) const; public: void visitChildScope( ScopeVisitor &visitor ); @@ -119,16 +135,22 @@ { public: // overridden from NamespaceScope virtual void accept( ScopeVisitor &visitor ); + virtual Scope *getOutterScope() const; }; class AnonymousNamespaceScope : public NamespaceScope { +public: + AnonymousNamespaceScope( GlobalNamespaceScope &parentScope ); + public: // overridden from NamespaceScope virtual void accept( ScopeVisitor &visitor ); + virtual Scope *getOutterScope() const; private: + GlobalNamespaceScope &parentScope_; }; @@ -142,6 +164,8 @@ public: // overridden from NamespaceScope virtual void accept( ScopeVisitor &visitor ); + virtual Scope *getOutterScope() const; + virtual TextId getScopeSymbol() const; private: LocatedSymbol id_; @@ -152,6 +176,15 @@ class TypeDeclaration : public Declaration { public: + bool hasSymbol() const; + + TextId getTypeSymbol() const; + + const Location &getLocation() const; + + virtual const LocatedSymbol &getSymbol() const = 0; + + virtual Scope &getDeclarationScope() const = 0; }; typedef CppTL::AnyEnumerator<EnumValueDecl *> EnumEnumValueDecl; @@ -165,18 +198,15 @@ EnumTypeDecl( const LocatedSymbol &id, Scope &parentScope ); - bool hasSymbol() const; - - const Location &getLocation() const; - - const LocatedSymbol &getSymbol() const; - void addEnumValue( EnumValueDecl &enumValue ); EnumEnumValueDecl enumEnumValues(); public: // overridden from TypeDeclaration virtual void accept( DeclarationVisitor &visitor ); + virtual TypeDeclaration *isNamedType( TextId id ); + virtual const LocatedSymbol &getSymbol() const; + virtual Scope &getDeclarationScope() const; private: typedef std::vector<EnumValueDecl *> EnumValues; @@ -202,7 +232,23 @@ LocatedSymbol id_; }; +class BaseClassInfo +{ +public: + BaseClassInfo( TypeDeclaration &type, + AccessLevel access ) + : type_( &type ) + , access_( access ) + { + } + TypeDeclaration *type_; + AccessLevel access_; +}; + +typedef CppTL::AnyEnumerator<BaseClassInfo> EnumBaseClass; + + class ClassDecl : public Scope , public TypeDeclaration { @@ -219,29 +265,36 @@ ClassKey getClassKey() const; - bool hasSymbol() const; + void visitChildScope( ScopeVisitor &visitor ); + void visitChildDeclaration( DeclarationVisitor &visitor ); - const Location &getLocation() const; + void addBaseClass( TypeDeclaration &type, AccessLevel access ); - const LocatedSymbol &getSymbol() const; + EnumBaseClass enumBaseClasses() const; - void visitChildScope( ScopeVisitor &visitor ); - void visitChildDeclaration( DeclarationVisitor &visitor ); - public: // overridden from Scope virtual void addNamedDeclaration( TextId id, Declaration &decl ); virtual void addAnonymousDeclaration( Declaration &decl ); virtual void addScope( Scope &scope ); virtual void accept( ScopeVisitor &visitor ); + virtual TextId getScopeSymbol() const; + virtual Scope *resolveQualifiedScope( TextId id ); + virtual Scope *getOutterScope() const; + virtual TypeDeclaration *resolveQualifiedType( TextId id ) const; -public: // overridden from Declaration +public: // overridden from TypeDeclaration virtual void accept( DeclarationVisitor &visitor ); virtual Scope *isScope(); + virtual TypeDeclaration *isNamedType( TextId id ); + virtual const LocatedSymbol &getSymbol() const; + virtual Scope &getDeclarationScope() const; private: ChildScopes scopes_; typedef std::vector<Declaration *> Declarations; Declarations declarations_; + typedef std::vector<BaseClassInfo> Bases; + Bases bases_; LocatedSymbol id_; ClassKey classKey_; Scope &parentScope_; @@ -267,12 +320,24 @@ const LocatedSymbol &id, Scope &scope, AccessLevel accessLevel ); + + Scope &declareOrResolveQualifiedScope( const LocatedSymbol &id, + Scope &scope ); + Scope &declareOrResolveUnqualifiedScope( const LocatedSymbol &id, + Scope &scope ); + Scope &declareUnknownScope( const LocatedSymbol &id, Scope &scope ); + + TypeDeclaration &declareOrResolveType( const LocatedSymbol &id, + Scope &scope ); + TypeDeclaration &declareUnknownType( const LocatedSymbol &id, Scope &scope ); + private: GlobalNamespaceScope globalNamespace_; CppTL::BatchAllocator<NamespaceDecl> namespaceDeclAlloc_; CppTL::BatchAllocator<EnumTypeDecl> enumTypeDeclAlloc_; CppTL::BatchAllocator<EnumValueDecl> enumValueAlloc_; CppTL::BatchAllocator<ClassDecl> classDeclAlloc_; + //CppTL::BatchAllocator<UnknownScope> unknownScopeAlloc_; }; Modified: rfta/trunk/include/rfta/token.h =================================================================== --- rfta/trunk/include/rfta/token.h 2007-04-20 07:29:43 UTC (rev 22) +++ rfta/trunk/include/rfta/token.h 2007-04-22 14:22:01 UTC (rev 23) @@ -156,6 +156,11 @@ return repository_.getIdentifierText( symbol.text_ ); } + const CppTL::ConstString &getSymbolText( TextId text ) const + { + return repository_.getIdentifierText( text ); + } + CppTL::ConstString getTokenText( const Token &token ) const { switch ( getTokenStorageMethod(token.tokenId_) ) Modified: rfta/trunk/makefiles/vs8/test_rftaparser.vcproj =================================================================== --- rfta/trunk/makefiles/vs8/test_rftaparser.vcproj 2007-04-20 07:29:43 UTC (rev 22) +++ rfta/trunk/makefiles/vs8/test_rftaparser.vcproj 2007-04-22 14:22:01 UTC (rev 23) @@ -186,6 +186,14 @@ RelativePath="..\..\src\test_rftaparser\main.cpp" > </File> + <File + RelativePath=".\parser.log" + > + </File> + <File + RelativePath=".\parser.out" + > + </File> </Files> <Globals> </Globals> Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-20 07:29:43 UTC (rev 22) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-22 14:22:01 UTC (rev 23) @@ -99,8 +99,8 @@ ::base_specifier $qualifiers=(?'virtual' ?access_specifier ?'virtual') - $id=(identifier) - !addBaseClassToClassDeclaration[$qualifiers,$id] + type_id + !addBaseClassToClassDeclaration[$qualifiers] ::base_clause ':' base_specifier *( ',' base_specifier ) @@ -171,9 +171,10 @@ ::init_declarator *ptr_operator ( 'operator' ( operator - | simple_type_specifier ) + | simple_type_specifier + ) *fn_suffix | '~' identifier '(' ')' #destructor - | identifier + | identifier *fn_suffix ) ::ptr_operator # ignore pointer to member @@ -183,11 +184,12 @@ '(' *(~(')')) ')' + ?($cv1=(cv_qualifier_seq)) # add throw clause... ::fn_definition '{' - *( ~('{') | statement_skip_error_compound ) + *( ~('{' | '}' | %T_EOF) | statement_skip_error_compound ) '}' ::storage_class_specifier @@ -204,7 +206,8 @@ | 'explicit') ) ::simple_typeid - fundamental_type | identifier + fundamental_type + | ?'::' identifier *( '::' identifier ) # type specifier used for conversion operator ::simple_type_specifier @@ -272,3 +275,8 @@ '{' +( skip_block_initializer | ~( '}' | %T_EOF ) ) '}' + +::type_id + $gscope=(?'::') !beginTypeId[$gscope] + *( $scope=(identifier) '::' !addTypeIdScope[$scope] ) + $typeId=(identifier) !endTypeId[$typeId] \ No newline at end of file Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-20 07:29:43 UTC (rev 22) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-22 14:22:01 UTC (rev 23) @@ -28,6 +28,8 @@ , contentManager_( contentManager ) , currentEnumDecl_( 0 ) , currentClassDecl_( 0 ) + , typeIdScope_( 0 ) + , typeId_( 0 ) { namespaceScopes_.push( &declManager.getGlobalNamespaceScope() ); accessLevels_.push( accessPublic ); @@ -121,10 +123,30 @@ void -CxxParserAction::addBaseClassToClassDeclaration( const TokenScannerPosRange &qualifiers, - const TokenScannerPosRange &id ) +CxxParserAction::addBaseClassToClassDeclaration( const TokenScannerPosRange &qualifiers ) { - // @todo + unsigned int access = accessPrivate; + for ( TokenScannerPos pos = qualifiers.start_; pos != qualifiers.end_; ++pos ) + { + switch ( pos->tokenId_ ) + { + case T_PUBLIC: + access = (access & ~accessVisibility) | accessPublic; + break; + case T_PROTECTED: + access = (access & ~accessVisibility) | accessProtected; + break; + case T_PRIVATE: + access = (access & ~accessVisibility) | accessPrivate; + break; + case T_VIRTUAL: + access |= accessVirtual; + break; + default: + CPPTL_DEBUG_ASSERT_UNREACHABLE; + } + } + currentClassDecl_->addBaseClass( *typeId_, AccessLevel( access ) ); } @@ -174,6 +196,47 @@ void +CxxParserAction::beginTypeId(const TokenScannerPosRange &gscope) +{ + if ( gscope.length() == 0 ) + { + typeIdScope_ = &getCurrentScope(); + typeIdQualifiedLookUp_ = false; + } + else + { + typeIdScope_ = &decls_.getGlobalNamespaceScope(); + typeIdQualifiedLookUp_ = true; + } + typeId_ = 0; +} + + +void +CxxParserAction::addTypeIdScope(const TokenScannerPosRange &scope) +{ + if ( typeIdQualifiedLookUp_ ) + { + typeIdScope_ = &( decls_.declareOrResolveQualifiedScope( *(scope.start_), + getCurrentScope() ) ); + } + else + { + typeIdScope_ = &( decls_.declareOrResolveUnqualifiedScope( *(scope.start_), + getCurrentScope() ) ); + typeIdQualifiedLookUp_ = true; + } +} + + +void +CxxParserAction::endTypeId(const TokenScannerPosRange &typeId) +{ + typeId_ = &( decls_.declareOrResolveType( *(typeId.start_), *typeIdScope_ ) ); +} + + +void CxxParserAction::handleDeclarationError(const TokenScannerPosRange &tokens) { addError( tokens, "Error in declaration" ); Modified: rfta/trunk/src/lib_rftaparser/cxxtype.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-20 07:29:43 UTC (rev 22) +++ rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-22 14:22:01 UTC (rev 23) @@ -18,6 +18,26 @@ { } + +Scope * +Scope::resolveUnqualifiedScope( TextId id ) +{ + Scope *scope = resolveQualifiedScope( id ); + if ( scope == 0 ) + { + for ( Scope *outterScope = getOutterScope(); + outterScope != 0; + outterScope = outterScope->getOutterScope() ) + { + scope = outterScope->resolveQualifiedScope( id ); + if ( scope != 0 ) + break; + } + } + return scope; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class NamespaceScope @@ -45,6 +65,43 @@ } +Scope * +NamespaceScope::resolveQualifiedScope( TextId id ) +{ + ChildScopes::Enum enumerator = scopes_.enumItems(); + while ( enumerator.hasNext() ) + { + Scope &scope = enumerator.next(); + if ( scope.getScopeSymbol() == id ) + return &scope; + } + return 0; +} + + +TextId +NamespaceScope::getScopeSymbol() const +{ + return nullTextId(); +} + + +TypeDeclaration * +NamespaceScope::resolveQualifiedType( TextId id ) const +{ + Declarations::const_iterator it = declarations_.begin(); + Declarations::const_iterator itEnd = declarations_.end(); + for ( ; it != itEnd; ++it ) + { + Declaration *declaration = *it; + TypeDeclaration *type = declaration->isNamedType( id ); + if ( type ) + return type; + } + return 0; +} + + void NamespaceScope::visitChildScope( ScopeVisitor &visitor ) { @@ -88,12 +145,25 @@ } +TypeDeclaration * +Declaration::isNamedType( TextId id ) +{ + return 0; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class AnonymousNamespaceScope // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +AnonymousNamespaceScope::AnonymousNamespaceScope( GlobalNamespaceScope &parentScope ) + : parentScope_( parentScope ) +{ +} + + void AnonymousNamespaceScope::accept( ScopeVisitor &visitor ) { @@ -101,6 +171,13 @@ } +Scope * +AnonymousNamespaceScope::getOutterScope() const +{ + return &parentScope_; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class NamespaceDecl @@ -114,6 +191,13 @@ } +Scope * +GlobalNamespaceScope::getOutterScope() const +{ + return 0; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class NamespaceDecl @@ -128,6 +212,13 @@ } +TextId +NamespaceDecl::getScopeSymbol() const +{ + return id_.text_; +} + + const LocatedSymbol & NamespaceDecl::getSymbol() const { @@ -142,8 +233,42 @@ } +Scope * +NamespaceDecl::getOutterScope() const +{ + return &parentScope_; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +// class TypeDeclaration +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +bool +TypeDeclaration::hasSymbol() const +{ + return getSymbol().text_ != nullTextId(); +} + + +TextId +TypeDeclaration::getTypeSymbol() const +{ + return getSymbol().text_; +} + + +const Location & +TypeDeclaration::getLocation() const +{ + return getSymbol(); +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// // class EnumTypeDecl // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -163,20 +288,6 @@ } -bool -EnumTypeDecl::hasSymbol() const -{ - return id_.text_ != nullTextId(); -} - - -const Location & -EnumTypeDecl::getLocation() const -{ - return id_; -} - - const LocatedSymbol & EnumTypeDecl::getSymbol() const { @@ -206,6 +317,22 @@ } +Scope & +EnumTypeDecl::getDeclarationScope() const +{ + return parentScope_; +} + + +TypeDeclaration * +EnumTypeDecl::isNamedType( TextId id ) +{ + if ( id == id_.text_ ) + return this; + return 0; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class EnumValueDecl @@ -271,24 +398,61 @@ return classKey_; } +const LocatedSymbol & +ClassDecl::getSymbol() const +{ + return id_; +} -bool -ClassDecl::hasSymbol() const + +TextId +ClassDecl::getScopeSymbol() const { - return id_.text_ != nullTextId(); + return id_.text_; } -const Location & -ClassDecl::getLocation() const +Scope * +ClassDecl::resolveQualifiedScope( TextId id ) +{ // copied from NamespaceScope + ChildScopes::Enum enumerator = scopes_.enumItems(); + while ( enumerator.hasNext() ) + { + Scope &scope = enumerator.next(); + if ( scope.getScopeSymbol() == id ) + return &scope; + } + return 0; +} + + +TypeDeclaration * +ClassDecl::resolveQualifiedType( TextId id ) const +{ // copied from NamespaceScope + Declarations::const_iterator it = declarations_.begin(); + Declarations::const_iterator itEnd = declarations_.end(); + for ( ; it != itEnd; ++it ) + { + Declaration *declaration = *it; + TypeDeclaration *type = declaration->isNamedType( id ); + if ( type ) + return type; + } + return 0; +} + + +Scope * +ClassDecl::getOutterScope() const { - return id_; + return &parentScope_; } -const LocatedSymbol & -ClassDecl::getSymbol() const + +Scope & +ClassDecl::getDeclarationScope() const { - return id_; + return parentScope_; } @@ -314,6 +478,21 @@ void +ClassDecl::addBaseClass( TypeDeclaration &type, AccessLevel access ) +{ + BaseClassInfo info( type, access ); + bases_.push_back( info ); +} + + +EnumBaseClass +ClassDecl::enumBaseClasses() const +{ + return CppTL::Enum::anyContainer( bases_, CppTL::Type<BaseClassInfo>() ); +} + + +void ClassDecl::accept( ScopeVisitor &visitor ) { visitor.visitClassScope( *this ); @@ -354,6 +533,15 @@ } +TypeDeclaration * +ClassDecl::isNamedType( TextId id ) +{ + if ( id == id_.text_ ) + return this; + return 0; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class DeclarationManager @@ -441,4 +629,52 @@ } +Scope & +DeclarationManager::declareOrResolveQualifiedScope( const LocatedSymbol &id, + Scope &scope ) +{ + Scope *resolvedScope = scope.resolveQualifiedScope( id.text_ ); + if ( resolvedScope == 0 ) + resolvedScope = &( declareUnknownScope( id, scope ) ); + return *resolvedScope; +} + + +Scope & +DeclarationManager::declareOrResolveUnqualifiedScope( const LocatedSymbol &id, + Scope &scope ) +{ + Scope *resolvedScope = scope.resolveUnqualifiedScope( id.text_ ); + if ( resolvedScope == 0 ) + resolvedScope = &( declareUnknownScope( id, scope ) ); + return *resolvedScope; +} + + +Scope & +DeclarationManager::declareUnknownScope( const LocatedSymbol &id, Scope &scope ) +{ + // dummy implementation + return declareNamedClass( classKeyClass, id, scope, accessPublic ); +} + +TypeDeclaration & +DeclarationManager::declareOrResolveType( const LocatedSymbol &id, + Scope &scope ) +{ + TypeDeclaration *resolvedType = scope.resolveQualifiedType( id.text_ ); + if ( resolvedType == 0 ) + resolvedType = &( declareUnknownType( id, scope ) ); + return *resolvedType; +} + + +TypeDeclaration & +DeclarationManager::declareUnknownType( const LocatedSymbol &id, Scope &scope ) +{ + // dummy implementation + return declareNamedClass( classKeyClass, id, scope, accessPublic ); +} + + } // namespace Rfta { Modified: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp 2007-04-20 07:29:43 UTC (rev 22) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-22 14:22:01 UTC (rev 23) @@ -11,6 +11,7 @@ #include <iostream> #include <stdexcept> #include <stdio.h> +#include <stdarg.h> /* Test program: - expect command, then source on stdin @@ -158,9 +159,24 @@ printScopeHeader( "class", getSymbolText(scope.getSymbol()).c_str() ); else printScopeHeader( "class", "<anonymous>" ); + Rfta::EnumBaseClass enumBase = scope.enumBaseClasses(); + if ( enumBase.hasNext() ) + { + printScopeHeader( "bases", "" ); + while ( enumBase.hasNext() ) + { + Rfta::BaseClassInfo info = enumBase.next(); + printLine( "type: %s", getQualifiedTypeId( *(info.type_) ).c_str() ); + } + printScopeFooter(); + } + printScopeHeader( "nested classes", "" ); scope.visitChildScope( *this ); + printScopeFooter(); + printScopeHeader( "members", "" ); scope.visitChildDeclaration( *this ); printScopeFooter(); + printScopeFooter(); } public: // Rfta::DeclarationVisitor @@ -198,12 +214,52 @@ return contentManager_.getSymbolText(symbol); } + CppTL::ConstString getText( Rfta::TextId text ) const + { + return contentManager_.getSymbolText(text); + } + + CppTL::ConstString getQualifiedTypeId( const Rfta::TypeDeclaration &type ) const + { + CppTL::ConstString typeName = getSymbolText( type.getSymbol() ); + Rfta::Scope *scope = &( type.getDeclarationScope() ); + while ( scope ) + { + if ( dynamic_cast<Rfta::GlobalNamespaceScope *>( scope ) ) + { + typeName = "::" + typeName; + break; + } + else if ( dynamic_cast<Rfta::AnonymousNamespaceScope *>( scope ) ) + { + typeName = "<anonymous>::"; + break; + } + else // class + { + typeName = getText( scope->getScopeSymbol() ) + "::" + typeName; + scope = scope->getOutterScope(); + } + } + return typeName; + } + void printScopeHeader( const std::string &type, const std::string &name ) { fprintf( fout_, "%s%s: %s {\n", indent_.c_str(), type.c_str(), name.c_str() ); indent_ += " "; } + void printLine( const char *format, ... ) + { + va_list list; + va_start( list, format ); + fprintf( fout_, "%s", indent_.c_str() ); + vfprintf( fout_, format, list ); + fprintf( fout_, "\n" ); + va_end( list ); + } + void printScopeFooter() { indent_.resize( indent_.length() - 3 ); @@ -271,7 +327,7 @@ Rfta::TokenContentManager contentManager; Rfta::CxxParser parser; - parser.enableTrace( contentManager ); + parser.enableTrace( contentManager, flog ); Rfta::FileId fileId = 1234; Rfta::TokenStream tokenStream( input.c_str(), input.c_str() + input.length(), contentManager, Added: rfta/trunk/testdata/cxxparser_ut/t_class_004_inheritance2.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_004_inheritance2.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_004_inheritance2.cpp 2007-04-22 14:22:01 UTC (rev 23) @@ -0,0 +1,25 @@ +namespace C4 { + class Class004A + { + public: + }; +} + +namespace C4B { + class Class004B : public C4::Class004A + { + public: + }; + + + namespace C4BA + { + class Class004C : public Class004B + { + }; + } +} + +struct Struct004D : public C4B::C4BA::Class004C +{ +}; \ No newline at end of file Added: rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance3.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance3.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_005_inheritance3.cpp 2007-04-22 14:22:01 UTC (rev 23) @@ -0,0 +1,3 @@ +class Struct005 : public std::exception +{ +}; \ No newline at end of file Added: rfta/trunk/testdata/cxxparser_ut/t_decl_005_function.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_decl_005_function.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_decl_005_function.cpp 2007-04-22 14:22:01 UTC (rev 23) @@ -0,0 +1,3 @@ +int decl005a(); + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-20 07:29:45
|
Revision: 22 http://rfta.svn.sourceforge.net/rfta/?rev=22&view=rev Author: blep Date: 2007-04-20 00:29:43 -0700 (Fri, 20 Apr 2007) Log Message: ----------- - added rough parsing of variable declarations. Modified Paths: -------------- rfta/trunk/include/rfta/cpptokens.h rfta/trunk/include/rfta/cpptokensid.h rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_003_data_members.cpp rfta/trunk/testdata/cxxparser_ut/t_decl_001_fundamental.cpp rfta/trunk/testdata/cxxparser_ut/t_decl_002_fundamental_init.cpp rfta/trunk/testdata/cxxparser_ut/t_decl_003_init_list.cpp rfta/trunk/testdata/cxxparser_ut/t_decl_004_unknown_type.cpp Modified: rfta/trunk/include/rfta/cpptokens.h =================================================================== --- rfta/trunk/include/rfta/cpptokens.h 2007-04-18 07:44:00 UTC (rev 21) +++ rfta/trunk/include/rfta/cpptokens.h 2007-04-20 07:29:43 UTC (rev 22) @@ -187,6 +187,8 @@ "MSEXT_ASM", "UNKNOWN", "LINE_CONT", + "<LAST_TOKEN>", + "NAMESPACE_ID" }; unsigned int id = BASEID_FROM_TOKEN(tokid)-T_FIRST_TOKEN; @@ -375,6 +377,8 @@ "__asm", "<UNKNOWN>", "\\newline" + "<LAST_TOKEN>", + "namespace_id" }; unsigned int id = BASEID_FROM_TOKEN(tokid)-T_FIRST_TOKEN; Modified: rfta/trunk/include/rfta/cpptokensid.h =================================================================== --- rfta/trunk/include/rfta/cpptokensid.h 2007-04-18 07:44:00 UTC (rev 21) +++ rfta/trunk/include/rfta/cpptokensid.h 2007-04-20 07:29:43 UTC (rev 22) @@ -267,11 +267,10 @@ // pseudo tokens to help streamlining macro replacement, these should not // returned from the lexer nor should these be returned from the pp-iterator - T_NONREPLACABLE_IDENTIFIER = TOKEN_FROM_ID(T_LAST_TOKEN+1, IdentifierTokenType), - T_PLACEHOLDER = TOKEN_FROM_ID(T_LAST_TOKEN+2, WhiteSpaceTokenType), - T_PLACEMARKER = TOKEN_FROM_ID(T_LAST_TOKEN+3, InternalTokenType), - T_PARAMETERBASE = TOKEN_FROM_ID(T_LAST_TOKEN+4, ParameterTokenType), - T_EXTPARAMETERBASE = TOKEN_FROM_ID(T_LAST_TOKEN+5, ExtParameterTokenType), + T_NAMESPACE_ID = TOKEN_FROM_ID(T_LAST_TOKEN+1, IdentifierTokenType), + T_TYPE_ID = TOKEN_FROM_ID(T_LAST_TOKEN+2, IdentifierTokenType), + T_TEMPLATE_ID = TOKEN_FROM_ID(T_LAST_TOKEN+3, IdentifierTokenType), + T_UNKNOWN_ID = TOKEN_FROM_ID(T_LAST_TOKEN+4, IdentifierTokenType), }; /////////////////////////////////////////////////////////////////////////////// Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-18 07:44:00 UTC (rev 21) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-20 07:29:43 UTC (rev 22) @@ -43,6 +43,7 @@ virtual void exitClassDeclaration(); virtual void setClassName(const TokenScannerPosRange &id); virtual void setMemberVisibility(const TokenScannerPosRange &access); + virtual bool declarationTypeIsSelfType(); private: void addError( const TokenScannerPosRange &tokens, Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-18 07:44:00 UTC (rev 21) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-20 07:29:43 UTC (rev 22) @@ -1,10 +1,10 @@ ::translation_unit - ?(declaration_seq) %T_EOF + ?(declaration_seq) %T_EOF # A.2 ::identifier - %T_IDENTIFIER + %T_IDENTIFIER ::statement_error # look-ahead is not a end of compound statement, then an error occurred @@ -26,63 +26,64 @@ # ############################## A.7: Declaration ############################ ::declaration_seq - +( =>( ~( %T_EOF | '}' ) ) *declaration ?declaration_error ) - + +( =>( ~( %T_EOF | '}' ) ) *declaration ?declaration_error ) + ::declaration - namespace_definition - | enum_specifier - | class_specifier - | empty_declaration + namespace_definition + | simple_declaration +# | enum_specifier +# | class_specifier + | empty_declaration ::empty_declaration - ';' + ';' ::declaration_error =>( ~( %T_EOF | '}' ) ) # look-ahead is not a end of declaration block, then error $error_tokens=( +statement_skip_token ?';' ) !handleDeclarationError[ $error_tokens ] - + # enum # ::enum_specifier - $enumStart=('enum') $id=(?identifier) '{' - !declareAndEnterEnum[$id,$enumStart] - ?enumerator_list - '}' ';' - + $enumStart=('enum') $id=(?identifier) '{' + !declareAndEnterEnum[$id,$enumStart] + ?enumerator_list + '}' + ::enumerator_list - enumerator_definition *( ',' enumerator_definition ) - + enumerator_definition *( ',' enumerator_definition ) + ::enumerator_definition - $id=(enumerator) - !declareEnumValue[$id] - ?( '=' skip_enum_constant_expression ) - + $id=(enumerator) + !declareEnumValue[$id] + ?( '=' skip_enum_constant_expression ) + ::enumerator - identifier + identifier ::skip_enum_constant_expression - +( skip_braced_expression | ~( '}' | ',' ) ) + +( skip_braced_expression | ~( '}' | ',' | ';' ) ) ::skip_braced_expression - '(' - +( skip_braced_expression | ~')' ) - ')' - + '(' + +( skip_braced_expression | ~')' ) + ')' + # namespace # - + ::namespace_definition - 'namespace' $id=(?identifier) - '{' - !declareAndEnterNamespace[$id] - @[exitNamespaceDeclaration] - namespace_body - '}' + 'namespace' $id=(?identifier) + '{' + !declareAndEnterNamespace[$id] + @[exitNamespaceDeclaration] + namespace_body + '}' ::namespace_body - ?declaration_seq - + ?declaration_seq + # class # @@ -94,7 +95,7 @@ ?base_clause ::class_head_name - $id=(identifier) !setClassName[$id] + $id=(identifier) !setClassName[$id] ::base_specifier $qualifiers=(?'virtual' ?access_specifier ?'virtual') @@ -105,20 +106,21 @@ ':' base_specifier *( ',' base_specifier ) ::class_specifier - class_head + class_head '{' @[enterClassDeclaration exitClassDeclaration] ?member_specification - '}' ';' + '}' ::class_key - 'class' - | 'struct' - | 'union' + 'class' + | 'struct' + | 'union' #Notes: not included: #- opt(::) nested-name-specifier opt(template) unqualified-id -#::member_declaration +::member_declaration + simple_declaration # friend_simple_declaration # | typedef_simple_declaration # | class_forward_declaration @@ -136,10 +138,10 @@ $access=(access_specifier) ':' !setMemberVisibility[ $access ] ::member_specification - +( =>( ~( %T_EOF | '}' ) ) - *( access_specification ) #| member_declaration ) - ?member_declaration_error - ) + +( =>( ~( %T_EOF | '}' ) ) + *( access_specification | member_declaration ) + ?member_declaration_error + ) ::member_declaration_error =>( ~( %T_EOF | '}' ) ) # look-ahead is not a end of declaration block, then error @@ -149,3 +151,124 @@ ::member_declaration__skip_token ~( %T_EOF | '{' | '}' | ';' ) + +# X Y; => variable +# X Y(); => function +# X Y( ... ); => variable or function: declaration of unknown type named Y. + +::simple_declaration + ?storage_class_specifier + ?function_specifier + type_specifier + ( ';' + | ( => declarationTypeIsSelfType[] fn_suffix ( ';' | fn_definition ) ) + | ( init_declarator ( ?initializer *( ',' init_declarator ?initializer) ';' + | fn_definition + ) + ) + ) + +::init_declarator + *ptr_operator + ( 'operator' ( operator + | simple_type_specifier ) + | '~' identifier '(' ')' #destructor + | identifier + ) + +::ptr_operator # ignore pointer to member + ('*' | '&') ?cv_qualifier_seq + +::fn_suffix + '(' + *(~(')')) + ')' + # add throw clause... + +::fn_definition + '{' + *( ~('{') | statement_skip_error_compound ) + '}' + +::storage_class_specifier + $storageClass=( +( 'auto' + | 'register' + | 'static' + | 'extern' + | 'mutable' ) ) + +::function_specifier + $fn=( +('inline' + | '__inline' + | 'virtual' + | 'explicit') ) + +::simple_typeid + fundamental_type | identifier + +# type specifier used for conversion operator +::simple_type_specifier + ?($cv1=(cv_qualifier_seq)) + simple_typeid + ?($cv2=(cv_qualifier_seq)) + *ptr_operator + +::type_specifier + ?($cv1=(cv_qualifier_seq)) + ( simple_typeid + | class_specifier + | enum_specifier + ) ?($cv2=(cv_qualifier_seq)) + +::cv_qualifier_seq + +( 'const' | 'volatile' ) + +::fundamental_type + $builtins=( + +( 'bool' + | 'float' + | 'double' + | 'void' + | 'signed' + | 'unsigned' + | 'char' + | 'wchar_t' + | 'long' + | 'short' + | 'int' + | '__int8' + | '__int16' + | '__int32' + | '__int64' + ) + ) + +::operator + '+' | '-' | '*' | '/' | '%' + | '^' | '&' | '|' | '~' + | '!' | '=' | '<' | '>' + | '+=' | '-=' | '*=' | '/=' | '%=' + | '^=' | '&=' | '|=' + | '<<' | '>>' | '>>=' | '<<=' + | '==' | '!=' | '<=' | '>=' + | '&&' | '||' + | '++' | '--' + | ',' | '->*' | '->' + | '(' ')' | '[' ']' + | ('new' | 'delete') ?( '[' ']' ) + +::initializer + '=' skip_initializer_expression + +::skip_initializer_expression + +( skip_braced_expression | skip_block_initializer | ~( ',' | ';' ) ) + +::skip_braced_expression + '(' + +( skip_braced_expression | ~')' ) + ')' + +::skip_block_initializer + '{' + +( skip_block_initializer | ~( '}' | %T_EOF ) ) + '}' Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-18 07:44:00 UTC (rev 21) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-20 07:29:43 UTC (rev 22) @@ -209,4 +209,10 @@ } +bool +CxxParserAction::declarationTypeIsSelfType() +{ + return false; // @todo implement this +} + } // namespace Rfta { Added: rfta/trunk/testdata/cxxparser_ut/t_class_003_data_members.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_003_data_members.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_003_data_members.cpp 2007-04-20 07:29:43 UTC (rev 22) @@ -0,0 +1,6 @@ +class Class002 +{ + int x; + static const int y = 1234; + mutable long z; +}; Added: rfta/trunk/testdata/cxxparser_ut/t_decl_001_fundamental.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_decl_001_fundamental.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_decl_001_fundamental.cpp 2007-04-20 07:29:43 UTC (rev 22) @@ -0,0 +1,19 @@ +bool decl001_bool; +float decl001_float; +double decl001_double; +void decl001_void; +signed int decl001_signed_int; +int decl001_int; +unsigned int decl001_unsigned_int; +char decl001_char; +signed char decl001_signed_char; +unsigned char decl001_unsigned_char; +wchar_t decl001_wchar_t; +signed wchar_t decl001_signed_wchar_t; +unsigned wchar_t decl001_unsigned_wchar_t; +signed long decl001_signed_int; +long decl001_int; +unsigned long decl001_unsigned_int; +signed short decl001_signed_int; +short decl001_int; +unsigned short decl001_unsigned_int; Added: rfta/trunk/testdata/cxxparser_ut/t_decl_002_fundamental_init.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_decl_002_fundamental_init.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_decl_002_fundamental_init.cpp 2007-04-20 07:29:43 UTC (rev 22) @@ -0,0 +1,19 @@ +bool decl002_bool; +float decl002_float = 2.3; +double decl002_double = 7.5; +void decl002_void = 0; +signed int decl002_signed_int = -1; +int decl002_int = 3; +unsigned int decl002_unsigned_int = 4; +char decl002_char = 'c'; +signed char decl002_signed_char = -4; +unsigned char decl002_unsigned_char = 7; +wchar_t decl002_wchar_t = L'c'; +signed wchar_t decl002_signed_wchar_t = 75; +unsigned wchar_t decl002_unsigned_wchar_t = 85; +signed long decl002_signed_int = 1234; +long decl002_int = 456; +unsigned long decl002_unsigned_int = 456; +signed short decl002_signed_int = 45646; +short decl002_int = 45646; +unsigned short decl002_unsigned_int = 4564; Added: rfta/trunk/testdata/cxxparser_ut/t_decl_003_init_list.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_decl_003_init_list.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_decl_003_init_list.cpp 2007-04-20 07:29:43 UTC (rev 22) @@ -0,0 +1 @@ +int decl003a, decl003b = 1234; Added: rfta/trunk/testdata/cxxparser_ut/t_decl_004_unknown_type.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_decl_004_unknown_type.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_decl_004_unknown_type.cpp 2007-04-20 07:29:43 UTC (rev 22) @@ -0,0 +1,2 @@ +UInt8 decl004; + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-18 07:44:02
|
Revision: 21 http://rfta.svn.sourceforge.net/rfta/?rev=21&view=rev Author: blep Date: 2007-04-18 00:44:00 -0700 (Wed, 18 Apr 2007) Log Message: ----------- - added inheritance parsing. Modified Paths: -------------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-18 06:53:05 UTC (rev 20) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-18 07:44:00 UTC (rev 21) @@ -38,6 +38,7 @@ virtual void handleDeclarationError(const TokenScannerPosRange &error_tokens); virtual void handleStatementError(const TokenScannerPosRange &error_tokens); virtual void declareClass(const TokenScannerPosRange &ck, const TokenScannerPosRange &name); + virtual void addBaseClassToClassDeclaration(const TokenScannerPosRange &qualifiers, const TokenScannerPosRange &id); virtual void enterClassDeclaration(); virtual void exitClassDeclaration(); virtual void setClassName(const TokenScannerPosRange &id); Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-18 06:53:05 UTC (rev 20) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-18 07:44:00 UTC (rev 21) @@ -91,10 +91,19 @@ $ck=(class_key) $name=(?class_head_name) => ( ':' | '{' ) # look-ahead so !declareClass[] is only called on match !declareClass[$ck,$name] + ?base_clause ::class_head_name $id=(identifier) !setClassName[$id] +::base_specifier + $qualifiers=(?'virtual' ?access_specifier ?'virtual') + $id=(identifier) + !addBaseClassToClassDeclaration[$qualifiers,$id] + +::base_clause + ':' base_specifier *( ',' base_specifier ) + ::class_specifier class_head '{' Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-18 06:53:05 UTC (rev 20) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-18 07:44:00 UTC (rev 21) @@ -119,7 +119,16 @@ } } + void +CxxParserAction::addBaseClassToClassDeclaration( const TokenScannerPosRange &qualifiers, + const TokenScannerPosRange &id ) +{ + // @todo +} + + +void CxxParserAction::enterClassDeclaration() { classScopes_.push( currentClassDecl_ ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-18 06:53:07
|
Revision: 20 http://rfta.svn.sourceforge.net/rfta/?rev=20&view=rev Author: blep Date: 2007-04-17 23:53:05 -0700 (Tue, 17 Apr 2007) Log Message: ----------- - added basic class declaration support. Modified Paths: -------------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/include/rfta/cxxtype.h rfta/trunk/include/rfta/forwards.h rfta/trunk/include/rfta/token.h rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/src/lib_rftaparser/cxxtype.cpp rfta/trunk/src/test_rftaparser/main.cpp rfta/trunk/test/rftatest.py Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_class_001_empty.cpp rfta/trunk/testdata/cxxparser_ut/t_class_002_inheritance.cpp rfta/trunk/testdata/cxxparser_ut/t_transunit_error2.cpp Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-17 07:22:36 UTC (rev 19) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-18 06:53:05 UTC (rev 20) @@ -37,16 +37,27 @@ virtual void declareEnumValue(const TokenScannerPosRange &id); virtual void handleDeclarationError(const TokenScannerPosRange &error_tokens); virtual void handleStatementError(const TokenScannerPosRange &error_tokens); + virtual void declareClass(const TokenScannerPosRange &ck, const TokenScannerPosRange &name); + virtual void enterClassDeclaration(); + virtual void exitClassDeclaration(); + virtual void setClassName(const TokenScannerPosRange &id); + virtual void setMemberVisibility(const TokenScannerPosRange &access); private: void addError( const TokenScannerPosRange &tokens, const char *message ); + Scope &getCurrentScope(); + DeclarationManager &decls_; CppTL::Stack<NamespaceScope *> namespaceScopes_; + CppTL::Stack<ClassDecl *> classScopes_; + CppTL::Stack<AccessLevel> accessLevels_; EnumTypeDecl *currentEnumDecl_; std::deque<ErrorInfo> errors_; TokenContentManager &contentManager_; + LocatedSymbol className_; + ClassDecl *currentClassDecl_; //ScopeManager scopeManager_; }; Modified: rfta/trunk/include/rfta/cxxtype.h =================================================================== --- rfta/trunk/include/rfta/cxxtype.h 2007-04-17 07:22:36 UTC (rev 19) +++ rfta/trunk/include/rfta/cxxtype.h 2007-04-18 06:53:05 UTC (rev 20) @@ -13,6 +13,22 @@ namespace Rfta { +enum AccessLevel +{ + accessPublic = 1, + accessProtected, + accessPrivate +}; + + +enum ClassKey +{ + classKeyClass = 1, + classKeyStruct, + classKeyUnion +}; + + class ScopeVisitor { public: @@ -23,6 +39,7 @@ virtual void visitGlobalNamespaceScope( GlobalNamespaceScope &scope ) = 0; virtual void visitAnonymousNamespaceScope( AnonymousNamespaceScope &scope ) = 0; virtual void visitNamespaceDecl( NamespaceDecl &scope ) = 0; + virtual void visitClassScope( ClassDecl &scope ) = 0; }; @@ -34,6 +51,7 @@ virtual void addNamedDeclaration( TextId id, Declaration &decl ) = 0; virtual void addAnonymousDeclaration( Declaration &decl ) = 0; + virtual void addScope( Scope &scope ) = 0; virtual void accept( ScopeVisitor &visitor ) = 0; @@ -56,6 +74,8 @@ virtual void accept( DeclarationVisitor &visitor ) = 0; + virtual Scope *isScope(); + private: Declaration( const Declaration &other ); Declaration &operator =( const Declaration &other ); @@ -71,6 +91,7 @@ virtual void visitEnumTypeDecl( EnumTypeDecl &enumTypeDecl ) = 0; virtual void visitEnumValueDecl( EnumValueDecl &enumValueDecl ) = 0; + virtual void visitClassDecl( ClassDecl &classDecl ) = 0; }; @@ -79,9 +100,9 @@ public: // overridden from Scope virtual void addNamedDeclaration( TextId id, Declaration &typeDecl ); virtual void addAnonymousDeclaration( Declaration &typeDecl ); + virtual void addScope( Scope &scope ); public: - void addNamespace( NamespaceScope &scope ); void visitChildScope( ScopeVisitor &visitor ); void visitChildDeclaration( DeclarationVisitor &visitor ); @@ -107,6 +128,7 @@ public: // overridden from NamespaceScope virtual void accept( ScopeVisitor &visitor ); +private: }; @@ -181,6 +203,52 @@ }; +class ClassDecl : public Scope + , public TypeDeclaration +{ +public: + ClassDecl( ClassKey classKey, + const Location &location, + Scope &parentScope, + AccessLevel access ); + + ClassDecl( ClassKey classKey, + const LocatedSymbol &id, + Scope &parentScope, + AccessLevel access ); + + ClassKey getClassKey() const; + + bool hasSymbol() const; + + const Location &getLocation() const; + + const LocatedSymbol &getSymbol() const; + + void visitChildScope( ScopeVisitor &visitor ); + void visitChildDeclaration( DeclarationVisitor &visitor ); + +public: // overridden from Scope + virtual void addNamedDeclaration( TextId id, Declaration &decl ); + virtual void addAnonymousDeclaration( Declaration &decl ); + virtual void addScope( Scope &scope ); + virtual void accept( ScopeVisitor &visitor ); + +public: // overridden from Declaration + virtual void accept( DeclarationVisitor &visitor ); + virtual Scope *isScope(); + +private: + ChildScopes scopes_; + typedef std::vector<Declaration *> Declarations; + Declarations declarations_; + LocatedSymbol id_; + ClassKey classKey_; + Scope &parentScope_; + AccessLevel access_; +}; + + class DeclarationManager { public: @@ -191,11 +259,20 @@ EnumTypeDecl &declareEnum( const LocatedSymbol &id, Scope &scope ); EnumTypeDecl &declareAnonymousEnum( const Location &location, Scope &scope ); EnumValueDecl &declareEnumValue( const LocatedSymbol &id, EnumTypeDecl &enumType ); + ClassDecl &declareAnonymousClass( ClassKey classKey, + const Location &location, + Scope &scope, + AccessLevel accessLevel ); + ClassDecl &declareNamedClass( ClassKey classKey, + const LocatedSymbol &id, + Scope &scope, + AccessLevel accessLevel ); private: GlobalNamespaceScope globalNamespace_; CppTL::BatchAllocator<NamespaceDecl> namespaceDeclAlloc_; CppTL::BatchAllocator<EnumTypeDecl> enumTypeDeclAlloc_; CppTL::BatchAllocator<EnumValueDecl> enumValueAlloc_; + CppTL::BatchAllocator<ClassDecl> classDeclAlloc_; }; Modified: rfta/trunk/include/rfta/forwards.h =================================================================== --- rfta/trunk/include/rfta/forwards.h 2007-04-17 07:22:36 UTC (rev 19) +++ rfta/trunk/include/rfta/forwards.h 2007-04-18 06:53:05 UTC (rev 20) @@ -16,6 +16,7 @@ // cxxtype.h class AnonymousNamespaceScope; +class ClassDecl; class Declaration; class DeclarationManager; class DeclarationVisitor; Modified: rfta/trunk/include/rfta/token.h =================================================================== --- rfta/trunk/include/rfta/token.h 2007-04-17 07:22:36 UTC (rev 19) +++ rfta/trunk/include/rfta/token.h 2007-04-18 06:53:05 UTC (rev 20) @@ -199,7 +199,7 @@ TokenId originalTokenId; while ( true ) { - originalTokenId = lexer_.nextToken(); + originalTokenId = getNextTokenIdSkipPreprocessor(); unsigned int tokenType = originalTokenId & TokenTypeMask; if ( tokenType != EOLTokenType && tokenType != WhiteSpaceTokenType ) break; @@ -207,6 +207,47 @@ fillLastToken( token, originalTokenId ); } + TokenId getNextTokenIdSkipPreprocessor() + { + while ( true ) + { + TokenId originalTokenId = lexer_.nextToken(); + unsigned int tokenType = originalTokenId & TokenTypeMask; + switch ( tokenType ) + { + case PPTokenType: + case PPConditionalTokenType: + { + // skip until next EOL, but handle line continuation + bool lineContinuationFound = false; + while ( true ) + { + TokenId originalTokenId = lexer_.nextToken(); + switch ( originalTokenId ) + { + case T_NEWLINE: + if ( !lineContinuationFound ) + return originalTokenId; + lineContinuationFound = false; + break; + case T_LINECONT: + lineContinuationFound = true; + break; + case T_EOF: + return originalTokenId; + default: // skip anything else + break; + } + } + } + + break; + default: + return originalTokenId; + } + } + } + void getNextToken( Token &token ) { TokenId originalTokenId = lexer_.nextToken(); Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-17 07:22:36 UTC (rev 19) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-18 06:53:05 UTC (rev 20) @@ -31,7 +31,12 @@ ::declaration namespace_definition | enum_specifier + | class_specifier + | empty_declaration +::empty_declaration + ';' + ::declaration_error =>( ~( %T_EOF | '}' ) ) # look-ahead is not a end of declaration block, then error $error_tokens=( +statement_skip_token ?';' ) @@ -78,3 +83,60 @@ ::namespace_body ?declaration_seq + +# class +# + +::class_head + $ck=(class_key) $name=(?class_head_name) + => ( ':' | '{' ) # look-ahead so !declareClass[] is only called on match + !declareClass[$ck,$name] + +::class_head_name + $id=(identifier) !setClassName[$id] + +::class_specifier + class_head + '{' + @[enterClassDeclaration exitClassDeclaration] + ?member_specification + '}' ';' + +::class_key + 'class' + | 'struct' + | 'union' + +#Notes: not included: +#- opt(::) nested-name-specifier opt(template) unqualified-id +#::member_declaration +# friend_simple_declaration +# | typedef_simple_declaration +# | class_forward_declaration +# | enum_forward_declaration +# | common_member_declaration +# | using_declaration +# | template_declaration + +::access_specifier + 'public' + | 'protected' + | 'private' + +::access_specification + $access=(access_specifier) ':' !setMemberVisibility[ $access ] + +::member_specification + +( =>( ~( %T_EOF | '}' ) ) + *( access_specification ) #| member_declaration ) + ?member_declaration_error + ) + +::member_declaration_error + =>( ~( %T_EOF | '}' ) ) # look-ahead is not a end of declaration block, then error + $error_tokens=( +member_declaration__skip_token ?statement_skip_error_compound ?';' ) + !handleDeclarationError[ $error_tokens ] + +::member_declaration__skip_token + ~( %T_EOF | '{' | '}' | ';' ) + Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-17 07:22:36 UTC (rev 19) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-18 06:53:05 UTC (rev 20) @@ -27,8 +27,10 @@ : decls_( declManager ) , contentManager_( contentManager ) , currentEnumDecl_( 0 ) + , currentClassDecl_( 0 ) { namespaceScopes_.push( &declManager.getGlobalNamespaceScope() ); + accessLevels_.push( accessPublic ); } @@ -81,7 +83,88 @@ decls_.declareEnumValue( *(id.start_), *currentEnumDecl_ ); } + void +CxxParserAction::declareClass( const TokenScannerPosRange &ck, + const TokenScannerPosRange &name ) +{ + ClassKey classKey; + switch ( ck.start_->tokenId_ ) + { + case T_CLASS: + classKey = classKeyClass; + break; + case T_STRUCT: + classKey = classKeyStruct; + break; + case T_UNION: + classKey = classKeyUnion; + break; + default: + CPPTL_DEBUG_ASSERT_UNREACHABLE; + } + if ( name.length() == 0 ) + { + currentClassDecl_ = &decls_.declareAnonymousClass( classKey, + *(ck.start_), + getCurrentScope(), + accessLevels_.top() ); + } + else + { + currentClassDecl_ = &decls_.declareNamedClass( classKey, + className_, + getCurrentScope(), + accessLevels_.top() ); + } +} + +void +CxxParserAction::enterClassDeclaration() +{ + classScopes_.push( currentClassDecl_ ); + bool isClass = ( currentClassDecl_->getClassKey() == classKeyClass ); + AccessLevel access = isClass ? accessPrivate : accessPublic; + accessLevels_.push( access ); +} + + +void +CxxParserAction::exitClassDeclaration() +{ + accessLevels_.pop(); + classScopes_.pop(); +} + + +void +CxxParserAction::setClassName(const TokenScannerPosRange &id) +{ + className_ = *(id.start_); +} + + +void +CxxParserAction::setMemberVisibility(const TokenScannerPosRange &access) +{ + switch ( access.start_->tokenId_ ) + { + case T_PUBLIC: + accessLevels_.top() = accessPublic; + break; + case T_PROTECTED: + accessLevels_.top() = accessProtected; + break; + case T_PRIVATE: + accessLevels_.top() = accessPrivate; + break; + default: + CPPTL_DEBUG_ASSERT_UNREACHABLE; + } +} + + +void CxxParserAction::handleDeclarationError(const TokenScannerPosRange &tokens) { addError( tokens, "Error in declaration" ); @@ -107,4 +190,14 @@ errors_.push_front( ErrorInfo( startPos, endPos, message ) ); } + +Scope & +CxxParserAction::getCurrentScope() +{ + if ( classScopes_.empty() ) + return *(namespaceScopes_.top()); + return *(classScopes_.top()); +} + + } // namespace Rfta { Modified: rfta/trunk/src/lib_rftaparser/cxxtype.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-17 07:22:36 UTC (rev 19) +++ rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-18 06:53:05 UTC (rev 20) @@ -39,7 +39,7 @@ void -NamespaceScope::addNamespace( NamespaceScope &scope ) +NamespaceScope::addScope( Scope &scope ) { scopes_.push_front( scope ); } @@ -81,6 +81,13 @@ } +Scope * +Declaration::isScope() +{ + return 0; +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class AnonymousNamespaceScope @@ -117,6 +124,7 @@ : id_( id ) , parentScope_( parentScope ) { + parentScope_.addScope( *this ); } @@ -226,6 +234,128 @@ // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +// class ClassDecl +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +ClassDecl::ClassDecl( ClassKey classKey, + const Location &location, + Scope &parentScope, + AccessLevel access ) + : classKey_( classKey ) + , parentScope_( parentScope ) + , access_( access ) +{ + static_cast<Location &>( id_ ) = location; + id_.text_ = nullTextId(); + parentScope_.addScope( *this ); +} + + +ClassDecl::ClassDecl( ClassKey classKey, + const LocatedSymbol &id, + Scope &parentScope, + AccessLevel access ) + : classKey_( classKey ) + , id_( id ) + , parentScope_( parentScope ) + , access_( access ) +{ + parentScope_.addScope( *this ); +} + + +ClassKey +ClassDecl::getClassKey() const +{ + return classKey_; +} + + +bool +ClassDecl::hasSymbol() const +{ + return id_.text_ != nullTextId(); +} + + +const Location & +ClassDecl::getLocation() const +{ + return id_; +} + +const LocatedSymbol & +ClassDecl::getSymbol() const +{ + return id_; +} + + +void +ClassDecl::addNamedDeclaration( TextId id, Declaration &decl ) +{ + declarations_.push_back( &decl ); +} + + +void +ClassDecl::addAnonymousDeclaration( Declaration &decl ) +{ + declarations_.push_back( &decl ); +} + + +void +ClassDecl::addScope( Scope &scope ) +{ + scopes_.push_front( scope ); +} + + +void +ClassDecl::accept( ScopeVisitor &visitor ) +{ + visitor.visitClassScope( *this ); +} + + +void +ClassDecl::accept( DeclarationVisitor &visitor ) +{ + visitor.visitClassDecl( *this ); +} + + +Scope * +ClassDecl::isScope() +{ + return this; +} + + +void +ClassDecl::visitChildScope( ScopeVisitor &visitor ) +{ + ChildScopes::Enum enumerator = scopes_.enumItems(); + while ( enumerator.hasNext() ) + { + enumerator.next().accept( visitor ); + } +} + +void +ClassDecl::visitChildDeclaration( DeclarationVisitor &visitor ) +{ + Declarations::const_iterator it = declarations_.begin(); + Declarations::const_iterator itEnd = declarations_.end(); + for ( ; it != itEnd; ++it ) + (*it)->accept( visitor ); +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// // class DeclarationManager // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -243,7 +373,6 @@ { NamespaceScope *namespaceScope = new (namespaceDeclAlloc_.allocate()) NamespaceDecl( id, scope ); - scope.addNamespace( *namespaceScope ); return *namespaceScope; } // @@ -286,4 +415,30 @@ } +ClassDecl & +DeclarationManager::declareAnonymousClass( ClassKey classKey, + const Location &location, + Scope &scope, + AccessLevel accessLevel ) +{ + ClassDecl *classDecl = + new (classDeclAlloc_.allocate()) ClassDecl( classKey, location, scope, accessLevel ); + scope.addAnonymousDeclaration( *classDecl ); + return *classDecl; +} + + +ClassDecl & +DeclarationManager::declareNamedClass( ClassKey classKey, + const LocatedSymbol &id, + Scope &scope, + AccessLevel accessLevel ) +{ + ClassDecl *classDecl = + new (classDeclAlloc_.allocate()) ClassDecl( classKey, id, scope, accessLevel ); + scope.addNamedDeclaration( id.text_, *classDecl ); + return *classDecl; +} + + } // namespace Rfta { Modified: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp 2007-04-17 07:22:36 UTC (rev 19) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-18 06:53:05 UTC (rev 20) @@ -120,7 +120,7 @@ while ( enumErrors.hasNext() ) { const Rfta::ErrorInfo &error = enumErrors.next(); - std::string msg = input_.substr( error.start_, error.end_ ); + std::string msg = input_.substr( error.start_, error.end_ - error.start_); fprintf( fout_, "#=> Error: %s\n%s\n", error.message_.c_str(), CppTL::quoteMultiLineString( msg ).c_str() ); @@ -128,7 +128,7 @@ } public: // Rfta::ScopeVisitor - void visitGlobalNamespaceScope( Rfta::GlobalNamespaceScope &scope ) + virtual void visitGlobalNamespaceScope( Rfta::GlobalNamespaceScope &scope ) { printScopeHeader( "namespace", "<GlobalNamespace>" ); scope.visitChildScope( *this ); @@ -136,7 +136,7 @@ printScopeFooter(); } - void visitAnonymousNamespaceScope( Rfta::AnonymousNamespaceScope &scope ) + virtual void visitAnonymousNamespaceScope( Rfta::AnonymousNamespaceScope &scope ) { printScopeHeader( "namespace", "<anonymous>" ); scope.visitChildScope( *this ); @@ -144,7 +144,7 @@ printScopeFooter(); } - void visitNamespaceDecl( Rfta::NamespaceDecl &scope ) + virtual void visitNamespaceDecl( Rfta::NamespaceDecl &scope ) { printScopeHeader( "namespace", getSymbolText(scope.getSymbol()).c_str() ); scope.visitChildScope( *this ); @@ -152,6 +152,17 @@ printScopeFooter(); } + virtual void visitClassScope( Rfta::ClassDecl &scope ) + { + if ( scope.hasSymbol() ) + printScopeHeader( "class", getSymbolText(scope.getSymbol()).c_str() ); + else + printScopeHeader( "class", "<anonymous>" ); + scope.visitChildScope( *this ); + scope.visitChildDeclaration( *this ); + printScopeFooter(); + } + public: // Rfta::DeclarationVisitor virtual void visitEnumTypeDecl( Rfta::EnumTypeDecl &enumTypeDecl ) { @@ -173,6 +184,14 @@ fprintf( fout_, "%senum value: %s\n", indent_.c_str(), getSymbolText(enumValueDecl.getSymbol()).c_str() ); } + virtual void visitClassDecl( Rfta::ClassDecl &classDecl ) + { + if ( classDecl.hasSymbol() ) + fprintf( fout_, "%sclass: %s\n", indent_.c_str(), getSymbolText(classDecl.getSymbol()).c_str() ); + else + fprintf( fout_, "%sclass <anonymous>\n", indent_.c_str() ); + } + private: CppTL::ConstString getSymbolText( const Rfta::LocatedSymbol &symbol ) const { Modified: rfta/trunk/test/rftatest.py =================================================================== --- rfta/trunk/test/rftatest.py 2007-04-17 07:22:36 UTC (rev 19) +++ rfta/trunk/test/rftatest.py 2007-04-18 06:53:05 UTC (rev 20) @@ -69,7 +69,7 @@ else: print >> status_file, source_path, 'FAILED', return_code if process_stdout: - appendToFile( log_path, process_stdout ) + appendToFile( log_path, process_stdout.replace('\r\n','\n') ) if process_stderr and process_stderr != process_stdout: appendToFile( log_path, process_stderr ) return True @@ -100,9 +100,11 @@ output_path = out_basepath + '-parser.txt' eraseFile( log_path ) eraseFile( output_path ) + linesep = "-" * 78 + "\n" for source_path, source in source_provider: print 'Processing', source_path - appendToFile( log_path, "#SOURCELOG: " + source_path ) + appendToFile( log_path, linesep + "#SOURCELOG: " + source_path ) + appendToFile( output_path, linesep + "#SOURCEOUPUT: " + source_path ) test_runner( source, source_path, log_path, output_path, exe_path, status_file, **test_runner_kwargs ) status_file.close() if verbose_status: Added: rfta/trunk/testdata/cxxparser_ut/t_class_001_empty.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_001_empty.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_001_empty.cpp 2007-04-18 06:53:05 UTC (rev 20) @@ -0,0 +1,14 @@ +class Class001 +{ +}; + +struct Struct001 +{ +}; + + +union Union001 +{ + Class001 a; + Struct001 b; +}; Added: rfta/trunk/testdata/cxxparser_ut/t_class_002_inheritance.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_class_002_inheritance.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_class_002_inheritance.cpp 2007-04-18 06:53:05 UTC (rev 20) @@ -0,0 +1,16 @@ +class Class002A +{ +}; + +class Class002B +{ +}; + +class Class002C : public Class002A + , protected Class002B +{ +}; + +class Struct002D : private Class002C +{ +}; Added: rfta/trunk/testdata/cxxparser_ut/t_transunit_error2.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_transunit_error2.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_transunit_error2.cpp 2007-04-18 06:53:05 UTC (rev 20) @@ -0,0 +1 @@ +; \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-17 07:22:38
|
Revision: 19 http://rfta.svn.sourceforge.net/rfta/?rev=19&view=rev Author: blep Date: 2007-04-17 00:22:36 -0700 (Tue, 17 Apr 2007) Log Message: ----------- - added support for enum declaration & values. Modified Paths: -------------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/include/rfta/cxxtype.h rfta/trunk/include/rfta/forwards.h rfta/trunk/makefiles/vs8/rfta.suo rfta/trunk/makefiles/vs8/test_rftalexer.vcproj.ANABELLE.Zark.user rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/src/lib_rftaparser/cxxtype.cpp rfta/trunk/src/test_rftaparser/main.cpp rfta/trunk/test/rftaparser_unittest.py rfta/trunk/test/rftatest.py rfta/trunk/testdata/cxxparser_ut/t_enum_001_empty.cpp Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_enum_003.cpp rfta/trunk/testdata/cxxparser_ut/t_enum_004.cpp rfta/trunk/tools/rdpgen/TODO Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-17 07:22:36 UTC (rev 19) @@ -33,6 +33,8 @@ public: // overridden from CxxParserDelegate virtual void declareAndEnterNamespace(const TokenScannerPosRange &id); virtual void exitNamespaceDeclaration(); + virtual void declareAndEnterEnum(const TokenScannerPosRange &id, const TokenScannerPosRange &enumStart); + virtual void declareEnumValue(const TokenScannerPosRange &id); virtual void handleDeclarationError(const TokenScannerPosRange &error_tokens); virtual void handleStatementError(const TokenScannerPosRange &error_tokens); @@ -42,6 +44,7 @@ DeclarationManager &decls_; CppTL::Stack<NamespaceScope *> namespaceScopes_; + EnumTypeDecl *currentEnumDecl_; std::deque<ErrorInfo> errors_; TokenContentManager &contentManager_; //ScopeManager scopeManager_; Modified: rfta/trunk/include/rfta/cxxtype.h =================================================================== --- rfta/trunk/include/rfta/cxxtype.h 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/include/rfta/cxxtype.h 2007-04-17 07:22:36 UTC (rev 19) @@ -9,33 +9,10 @@ # include <cpptl/conststring.h> # include <deque> # include <stack> +# include <vector> namespace Rfta { -// namespace Impl { -// struct PhantomDeclarationId -// { -// }; -// struct PhantomScopeId : public PhantomDeclarationId -// { -// }; -// struct PhantomNamespaceId : public PhantomScopeId -// { -// }; -// struct PhantomClassId : public PhantomScopeId -// { -// }; -// struct PhantomEnumId : public PhantomDeclarationId -// { -// }; -// -// } // namespace Impl { -// -//typedef Impl::PhantomScopeId *ScopeId; -//typedef Impl::PhantomNamespaceId *NamespaceId; -//typedef Impl::PhantomEnumId *EnumId; - - class ScopeVisitor { public: @@ -55,6 +32,9 @@ Scope(); virtual ~Scope(); + virtual void addNamedDeclaration( TextId id, Declaration &decl ) = 0; + virtual void addAnonymousDeclaration( Declaration &decl ) = 0; + virtual void accept( ScopeVisitor &visitor ) = 0; private: @@ -74,22 +54,43 @@ Declaration(); virtual ~Declaration(); + virtual void accept( DeclarationVisitor &visitor ) = 0; + private: Declaration( const Declaration &other ); Declaration &operator =( const Declaration &other ); }; +class DeclarationVisitor +{ +public: + virtual ~DeclarationVisitor() + { + } + + virtual void visitEnumTypeDecl( EnumTypeDecl &enumTypeDecl ) = 0; + virtual void visitEnumValueDecl( EnumValueDecl &enumValueDecl ) = 0; +}; + + class NamespaceScope : public Scope { +public: // overridden from Scope + virtual void addNamedDeclaration( TextId id, Declaration &typeDecl ); + virtual void addAnonymousDeclaration( Declaration &typeDecl ); + public: void addNamespace( NamespaceScope &scope ); void visitChildScope( ScopeVisitor &visitor ); + void visitChildDeclaration( DeclarationVisitor &visitor ); private: // typedef CppTL::GrowHashMap<TextId, Declaration *> DeclarationsByName; // DeclarationsByName declarationsByName_; ChildScopes scopes_; + typedef std::vector<Declaration *> Declarations; + Declarations declarations_; }; @@ -109,8 +110,7 @@ }; -class NamespaceDecl : public Declaration - , public NamespaceScope +class NamespaceDecl : public NamespaceScope { public: NamespaceDecl( const LocatedSymbol &id, @@ -127,6 +127,60 @@ }; +class TypeDeclaration : public Declaration +{ +public: +}; + +typedef CppTL::AnyEnumerator<EnumValueDecl *> EnumEnumValueDecl; + +class EnumTypeDecl : public TypeDeclaration +{ +public: + EnumTypeDecl( const Location &location, + Scope &parentScope ); + + EnumTypeDecl( const LocatedSymbol &id, + Scope &parentScope ); + + bool hasSymbol() const; + + const Location &getLocation() const; + + const LocatedSymbol &getSymbol() const; + + void addEnumValue( EnumValueDecl &enumValue ); + + EnumEnumValueDecl enumEnumValues(); + +public: // overridden from TypeDeclaration + virtual void accept( DeclarationVisitor &visitor ); + +private: + typedef std::vector<EnumValueDecl *> EnumValues; + EnumValues enumValues_; + LocatedSymbol id_; + Scope &parentScope_; +}; + + +class EnumValueDecl : public Declaration +{ +public: + EnumValueDecl( const LocatedSymbol &id, + EnumTypeDecl &enumType ); + + const LocatedSymbol &getSymbol() const; + +public: // overridden from Declaration + virtual void accept( DeclarationVisitor &visitor ); + +private: + EnumTypeDecl &enumType_; + LocatedSymbol id_; +}; + + class DeclarationManager { public: @@ -134,10 +188,14 @@ NamespaceScope &declareNamespace( const LocatedSymbol &id, NamespaceScope &scope ); //ScopeId declareAnynonmousNamespace( const Location &location, ScopeId scope ); - //EnumId declareEnum( const LocatedSymbol &id, ScopeId scope ); + EnumTypeDecl &declareEnum( const LocatedSymbol &id, Scope &scope ); + EnumTypeDecl &declareAnonymousEnum( const Location &location, Scope &scope ); + EnumValueDecl &declareEnumValue( const LocatedSymbol &id, EnumTypeDecl &enumType ); private: GlobalNamespaceScope globalNamespace_; CppTL::BatchAllocator<NamespaceDecl> namespaceDeclAlloc_; + CppTL::BatchAllocator<EnumTypeDecl> enumTypeDeclAlloc_; + CppTL::BatchAllocator<EnumValueDecl> enumValueAlloc_; }; Modified: rfta/trunk/include/rfta/forwards.h =================================================================== --- rfta/trunk/include/rfta/forwards.h 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/include/rfta/forwards.h 2007-04-17 07:22:36 UTC (rev 19) @@ -18,12 +18,20 @@ class AnonymousNamespaceScope; class Declaration; class DeclarationManager; +class DeclarationVisitor; +class EnumTypeDecl; +class EnumValueDecl; class GlobalNamespaceScope; class NamespaceDecl; class NamespaceScope; class Scope; class ScopeVisitor; +class TypeDeclaration; +inline TextId nullTextId() { + return 0; +} + } // namespace Rfta { #endif // RFTA_FORWARDS_H_INCLUDED Modified: rfta/trunk/makefiles/vs8/rfta.suo =================================================================== (Binary files differ) Modified: rfta/trunk/makefiles/vs8/test_rftalexer.vcproj.ANABELLE.Zark.user =================================================================== --- rfta/trunk/makefiles/vs8/test_rftalexer.vcproj.ANABELLE.Zark.user 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/makefiles/vs8/test_rftalexer.vcproj.ANABELLE.Zark.user 2007-04-17 07:22:36 UTC (rev 19) @@ -11,7 +11,7 @@ <DebugSettings Command="$(TargetPath)" WorkingDirectory="$(IntDir)" - CommandArguments="-o $(IntDir)/lexer.out -l $(IntDir)/lexer.log --log-append ../../src/test_rftalexer/test.txt" + CommandArguments="-o $(IntDir)/lexer.out -l $(IntDir)/lexer.log --log-append --no-output ../../src/test_rftalexer/test.txt" Attach="false" DebuggerType="3" Remote="1" Modified: rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user =================================================================== --- rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user 2007-04-17 07:22:36 UTC (rev 19) @@ -11,7 +11,7 @@ <DebugSettings Command="$(TargetPath)" WorkingDirectory="" - CommandArguments="../../testdata/cxxparser_ut/t_transunit_error.cpp" + CommandArguments="../../testdata/cxxparser_ut/t_enum_003.cpp" Attach="false" DebuggerType="3" Remote="1" @@ -39,7 +39,7 @@ <DebugSettings Command="$(TargetPath)" WorkingDirectory="" - CommandArguments="../../testdata/cxxparser_ut/t001001_ns_nested.cpp" + CommandArguments="../../testdata/cxxparser_ut/t_enum_003.cpp" Attach="false" DebuggerType="3" Remote="1" Modified: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-17 07:22:36 UTC (rev 19) @@ -30,13 +30,40 @@ ::declaration namespace_definition + | enum_specifier ::declaration_error =>( ~( %T_EOF | '}' ) ) # look-ahead is not a end of declaration block, then error $error_tokens=( +statement_skip_token ?';' ) !handleDeclarationError[ $error_tokens ] +# enum +# +::enum_specifier + $enumStart=('enum') $id=(?identifier) '{' + !declareAndEnterEnum[$id,$enumStart] + ?enumerator_list + '}' ';' +::enumerator_list + enumerator_definition *( ',' enumerator_definition ) + +::enumerator_definition + $id=(enumerator) + !declareEnumValue[$id] + ?( '=' skip_enum_constant_expression ) + +::enumerator + identifier + +::skip_enum_constant_expression + +( skip_braced_expression | ~( '}' | ',' ) ) + +::skip_braced_expression + '(' + +( skip_braced_expression | ~')' ) + ')' + # namespace # Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-17 07:22:36 UTC (rev 19) @@ -26,6 +26,7 @@ TokenContentManager &contentManager ) : decls_( declManager ) , contentManager_( contentManager ) + , currentEnumDecl_( 0 ) { namespaceScopes_.push( &declManager.getGlobalNamespaceScope() ); } @@ -61,6 +62,26 @@ void +CxxParserAction::declareAndEnterEnum(const TokenScannerPosRange &id, + const TokenScannerPosRange &enumStart) +{ + Scope ¤tScope = *namespaceScopes_.top(); + if ( id.length() == 0 ) + currentEnumDecl_ = &( decls_.declareAnonymousEnum( *(enumStart.start_), + currentScope ) ); + else + currentEnumDecl_ = &( decls_.declareEnum( *(id.start_), currentScope ) ); +} + + +void +CxxParserAction::declareEnumValue(const TokenScannerPosRange &id) +{ + CPPTL_ASSERT_MESSAGE( currentEnumDecl_ != 0, "Can only declare an enum value within an enum." ); + decls_.declareEnumValue( *(id.start_), *currentEnumDecl_ ); +} + +void CxxParserAction::handleDeclarationError(const TokenScannerPosRange &tokens) { addError( tokens, "Error in declaration" ); Modified: rfta/trunk/src/lib_rftaparser/cxxtype.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-17 07:22:36 UTC (rev 19) @@ -23,7 +23,22 @@ // class NamespaceScope // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// + void +NamespaceScope::addNamedDeclaration( TextId id, Declaration &decl ) +{ + declarations_.push_back( &decl ); +} + + +void +NamespaceScope::addAnonymousDeclaration( Declaration &decl ) +{ + declarations_.push_back( &decl ); +} + + +void NamespaceScope::addNamespace( NamespaceScope &scope ) { scopes_.push_front( scope ); @@ -40,7 +55,17 @@ } } +void +NamespaceScope::visitChildDeclaration( DeclarationVisitor &visitor ) +{ + Declarations::const_iterator it = declarations_.begin(); + Declarations::const_iterator itEnd = declarations_.end(); + for ( ; it != itEnd; ++it ) + (*it)->accept( visitor ); +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class Declaration @@ -109,9 +134,98 @@ } +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class EnumTypeDecl +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +EnumTypeDecl::EnumTypeDecl( const Location &location, + Scope &parentScope ) + : parentScope_( parentScope ) +{ + static_cast<Location &>( id_ ) = location; + id_.text_ = nullTextId(); +} +EnumTypeDecl::EnumTypeDecl( const LocatedSymbol &id, + Scope &parentScope ) + : id_( id ) + , parentScope_( parentScope ) +{ +} + + +bool +EnumTypeDecl::hasSymbol() const +{ + return id_.text_ != nullTextId(); +} + + +const Location & +EnumTypeDecl::getLocation() const +{ + return id_; +} + + +const LocatedSymbol & +EnumTypeDecl::getSymbol() const +{ + return id_; +} + + +void +EnumTypeDecl::addEnumValue( EnumValueDecl &enumValue ) +{ + enumValues_.push_back( &enumValue ); + parentScope_.addNamedDeclaration( enumValue.getSymbol().text_, enumValue ); +} + + +EnumEnumValueDecl +EnumTypeDecl::enumEnumValues() +{ + return CppTL::Enum::anyContainer( enumValues_, CppTL::Type<EnumValueDecl *>() ); +} + + +void +EnumTypeDecl::accept( DeclarationVisitor &visitor ) +{ + visitor.visitEnumTypeDecl( *this ); +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +// class EnumValueDecl +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +EnumValueDecl::EnumValueDecl( const LocatedSymbol &id, + EnumTypeDecl &enumType ) + : id_( id ) + , enumType_( enumType ) +{ +} + +const LocatedSymbol & +EnumValueDecl::getSymbol() const +{ + return id_; +} + + +void +EnumValueDecl::accept( DeclarationVisitor &visitor ) +{ + visitor.visitEnumValueDecl( *this ); +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// // class DeclarationManager // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -141,11 +255,35 @@ //} // // -//EnumId -//DeclarationManager::declareEnum( const LocatedSymbol &id, -// ScopeId scope ) -//{ -//} +EnumTypeDecl & +DeclarationManager::declareEnum( const LocatedSymbol &id, Scope &scope ) +{ + EnumTypeDecl *enumTypeDecl = + new (enumTypeDeclAlloc_.allocate()) EnumTypeDecl( id, scope ); + scope.addNamedDeclaration( id.text_, *enumTypeDecl ); + return *enumTypeDecl; +} + +EnumTypeDecl & +DeclarationManager::declareAnonymousEnum( const Location &location, Scope &scope ) +{ + EnumTypeDecl *enumTypeDecl = + new (enumTypeDeclAlloc_.allocate()) EnumTypeDecl( location, scope ); + scope.addAnonymousDeclaration( *enumTypeDecl ); + return *enumTypeDecl; +} + + +EnumValueDecl & +DeclarationManager::declareEnumValue( const LocatedSymbol &id, EnumTypeDecl &enumType ) +{ + EnumValueDecl *enumValueDecl = + new (enumValueAlloc_.allocate()) EnumValueDecl( id, enumType ); + enumType.addEnumValue( *enumValueDecl ); + return *enumValueDecl; +} + + } // namespace Rfta { Modified: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-17 07:22:36 UTC (rev 19) @@ -50,16 +50,25 @@ OutputFileHandle( const std::string &path, bool create, bool appendMode ) + : needClose_( false ) { failed_ = false; if ( create ) { - handle_ = fopen( path.c_str(), appendMode ? "at" : "wt" ); - if ( !handle_ ) + if ( path.empty() ) { - std::cout << "Failed to create output file '" << path << "'." << std::endl; - failed_ = true; + handle_ = stdout; } + else + { + handle_ = fopen( path.c_str(), appendMode ? "at" : "wt" ); + needClose_ = true; + if ( !handle_ ) + { + std::cout << "Failed to create output file '" << path << "'." << std::endl; + failed_ = true; + } + } } else { @@ -86,11 +95,13 @@ private: FILE *handle_; bool failed_; + bool needClose_; }; class DeclarationDumper : public Rfta::ScopeVisitor + , public Rfta::DeclarationVisitor { public: DeclarationDumper( FILE *fout, @@ -116,10 +127,12 @@ } } +public: // Rfta::ScopeVisitor void visitGlobalNamespaceScope( Rfta::GlobalNamespaceScope &scope ) { printScopeHeader( "namespace", "<GlobalNamespace>" ); scope.visitChildScope( *this ); + scope.visitChildDeclaration( *this ); printScopeFooter(); } @@ -127,6 +140,7 @@ { printScopeHeader( "namespace", "<anonymous>" ); scope.visitChildScope( *this ); + scope.visitChildDeclaration( *this ); printScopeFooter(); } @@ -134,9 +148,31 @@ { printScopeHeader( "namespace", getSymbolText(scope.getSymbol()).c_str() ); scope.visitChildScope( *this ); + scope.visitChildDeclaration( *this ); printScopeFooter(); } +public: // Rfta::DeclarationVisitor + virtual void visitEnumTypeDecl( Rfta::EnumTypeDecl &enumTypeDecl ) + { + if ( enumTypeDecl.hasSymbol() ) + printScopeHeader( "enum", getSymbolText(enumTypeDecl.getSymbol()).c_str() ); + else + printScopeHeader( "enum", "<anonymous>" ); + Rfta::EnumEnumValueDecl enumValues = enumTypeDecl.enumEnumValues(); + while ( enumValues.hasNext() ) + { + Rfta::EnumValueDecl *enumValueDecl = enumValues.next(); + fprintf( fout_, "%svalue: %s\n", indent_.c_str(), getSymbolText(enumValueDecl->getSymbol()).c_str() ); + } + printScopeFooter(); + } + + virtual void visitEnumValueDecl( Rfta::EnumValueDecl &enumValueDecl ) + { + fprintf( fout_, "%senum value: %s\n", indent_.c_str(), getSymbolText(enumValueDecl.getSymbol()).c_str() ); + } + private: CppTL::ConstString getSymbolText( const Rfta::LocatedSymbol &symbol ) const { Modified: rfta/trunk/test/rftaparser_unittest.py =================================================================== --- rfta/trunk/test/rftaparser_unittest.py 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/test/rftaparser_unittest.py 2007-04-17 07:22:36 UTC (rev 19) @@ -15,7 +15,8 @@ import rftatest RESULT_DIR = os.path.join( rftatest.TESTRESULT_DIR, 'parser_unittests' ) -PARSER_PATH = r'..\build\test_rftaparser_Release\test_rftaparser.exe' +##PARSER_PATH = r'..\build\test_rftaparser_Release\test_rftaparser.exe' +PARSER_PATH = r'..\build\test_rftaparser_Debug\test_rftaparser.exe' if __name__ == '__main__': class ParserTestRunner(rftatest.TestRunner): @@ -23,5 +24,6 @@ rftatest.TestRunner.__init__( self, PARSER_PATH ) self.output_file_suffix = '-parser.txt' - ParserTestRunner().runFileSystemProject( RESULT_DIR, os.path.join( rftatest.TESTDATA_DIR, 'cxxparser_ut' ) ) + ParserTestRunner().runFileSystemProject( RESULT_DIR, os.path.join( rftatest.TESTDATA_DIR, 'cxxparser_ut' ), + verbose_status = True ) Modified: rfta/trunk/test/rftatest.py =================================================================== --- rfta/trunk/test/rftatest.py 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/test/rftatest.py 2007-04-17 07:22:36 UTC (rev 19) @@ -46,8 +46,8 @@ output_path, exe_path, status_file, - append_to_log = 'True', - append_to_output = 'True', + append_to_log = True, + append_to_output = True, extra_flags = () ): cmd = ( exe_path, '-o', output_path, '-l', log_path ) if append_to_log: @@ -56,7 +56,7 @@ cmd += ('--output-append', ) cmd += extra_flags try: - print 'Running', cmd +## print 'Running', cmd return_code = 1 process = subprocess.Popen( cmd, stdin = subprocess.PIPE, @@ -91,9 +91,11 @@ result_dir, test_runner, exe_path, + verbose_status = False, **test_runner_kwargs ): out_basepath = os.path.join( result_dir, os.path.split( os.path.splitext(project_name)[0] )[1] ) - status_file = file( out_basepath + '-status.txt', 'wt' ) + status_path = out_basepath + '-status.txt' + status_file = file( status_path, 'wt' ) log_path = out_basepath + '-log.txt' output_path = out_basepath + '-parser.txt' eraseFile( log_path ) @@ -103,6 +105,8 @@ appendToFile( log_path, "#SOURCELOG: " + source_path ) test_runner( source, source_path, log_path, output_path, exe_path, status_file, **test_runner_kwargs ) status_file.close() + if verbose_status: + print file(status_path,'rt').read() class TestRunner: def __init__( self, exe_path, **runner_kwargs ): @@ -113,16 +117,19 @@ self.output_file_suffix = '-lexer.txt' self.keep_output = False - def runProjectTests( self, project_name, source_provider, result_dir ): + def runProjectTests( self, project_name, source_provider, result_dir, verbose_status = False ): return runProjectTests( project_name, source_provider, result_dir, self.test_runner, - self.exe_path, **self.test_runner_kwargs ) + self.exe_path, verbose_status = verbose_status, + **self.test_runner_kwargs ) - def runZippedProjects( self, result_dir, zip_dir = TESTDATA_PROJECTS_DIR ): + def runZippedProjects( self, result_dir, zip_dir = TESTDATA_PROJECTS_DIR, verbose_status = False ): zip_files = glob.glob( os.path.join( zip_dir, '*.zip' ) ) for zip_path in zip_files: print 'Analysing', zip_path - self.runProjectTests( zip_path, zipFileSourceProdiver( zip_path ), result_dir ) + self.runProjectTests( zip_path, zipFileSourceProdiver( zip_path ), result_dir, + verbose_status = verbose_status ) - def runFileSystemProject( self, result_dir, project_dir ): + def runFileSystemProject( self, result_dir, project_dir, verbose_status = False ): print 'Processing', project_dir - self.runProjectTests( project_dir, fileSystemSourceProvider( project_dir ), result_dir ) + self.runProjectTests( project_dir, fileSystemSourceProvider( project_dir ), result_dir, + verbose_status = verbose_status ) Modified: rfta/trunk/testdata/cxxparser_ut/t_enum_001_empty.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_enum_001_empty.cpp 2007-04-15 22:40:17 UTC (rev 18) +++ rfta/trunk/testdata/cxxparser_ut/t_enum_001_empty.cpp 2007-04-17 07:22:36 UTC (rev 19) @@ -1,3 +1,3 @@ -enum T002000_E1 +enum t_enum_001_empty { }; Added: rfta/trunk/testdata/cxxparser_ut/t_enum_003.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_enum_003.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_enum_003.cpp 2007-04-17 07:22:36 UTC (rev 19) @@ -0,0 +1,4 @@ +enum t_enum_003_value1_assign +{ + assign_value1 = (712+(4*5)) +}; Added: rfta/trunk/testdata/cxxparser_ut/t_enum_004.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_enum_004.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_enum_004.cpp 2007-04-17 07:22:36 UTC (rev 19) @@ -0,0 +1,40 @@ +enum t_enum_003_empty +{ +}; + +enum t_enum_003_value1 +{ + value1 +}; + +enum t_enum_003_value1_assign +{ + assign_value1 = (712+(4*5)) +}; + +enum t_enum_003_valuen +{ + valuen_value1, + valuen_value2, + valuen_value3, + valuen_value4 +}; + + +enum +{ +}; + + +enum +{ + anonymous_value1_assign = 21 + 4 +}; + + +enum +{ + anonymous_value1, + anonymous_value2, + anonymous_value3 +}; Added: rfta/trunk/tools/rdpgen/TODO =================================================================== --- rfta/trunk/tools/rdpgen/TODO (rev 0) +++ rfta/trunk/tools/rdpgen/TODO 2007-04-17 07:22:36 UTC (rev 19) @@ -0,0 +1 @@ +- two local subrules with same delegate parameter names will collide. Detect this and change names. \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-15 22:40:18
|
Revision: 18 http://rfta.svn.sourceforge.net/rfta/?rev=18&view=rev Author: blep Date: 2007-04-15 15:40:17 -0700 (Sun, 15 Apr 2007) Log Message: ----------- - added unit tests runner for parser Modified Paths: -------------- rfta/trunk/test/rftatest.py rfta/trunk/test/testresultbrowser.py Added Paths: ----------- rfta/trunk/test/rftaparser_unittest.py rfta/trunk/testresult/parser_unittests/ Added: rfta/trunk/test/rftaparser_unittest.py =================================================================== --- rfta/trunk/test/rftaparser_unittest.py (rev 0) +++ rfta/trunk/test/rftaparser_unittest.py 2007-04-15 22:40:17 UTC (rev 18) @@ -0,0 +1,27 @@ +# Iterates over all the zipped source files contained in the ROOT/testdata directory +# and parser them with RFTA parser. +# Processing output for each zip archive is in XYZ-EXT.txt files, where XYZ +# is the zip file basename without extension, and where EXT is: +# -log: log generated by the lexer (errors detail). +# -status: indicates if an occurred for each files +# -parser: parser declaration dump for all parsed file of the archive +# +# Results can be browsed using the testresultbrowser.py script. + +# Requires python 2.4 (due to subprocess module) + +import glob +import os.path +import rftatest + +RESULT_DIR = os.path.join( rftatest.TESTRESULT_DIR, 'parser_unittests' ) +PARSER_PATH = r'..\build\test_rftaparser_Release\test_rftaparser.exe' + +if __name__ == '__main__': + class ParserTestRunner(rftatest.TestRunner): + def __init__( self ): + rftatest.TestRunner.__init__( self, PARSER_PATH ) + self.output_file_suffix = '-parser.txt' + + ParserTestRunner().runFileSystemProject( RESULT_DIR, os.path.join( rftatest.TESTDATA_DIR, 'cxxparser_ut' ) ) + Modified: rfta/trunk/test/rftatest.py =================================================================== --- rfta/trunk/test/rftatest.py 2007-04-15 21:36:02 UTC (rev 17) +++ rfta/trunk/test/rftatest.py 2007-04-15 22:40:17 UTC (rev 18) @@ -23,6 +23,14 @@ source = archive.read( source_path ) yield (source_path, source) +def fileSystemSourceProvider( source_dir, is_source_file_pred = isSourceFile ): + for source_path in glob.glob( os.path.join( source_dir, '*' ) ): + if is_source_file_pred( source_path ): + source_file = file( source_path, 'rb' ) + source = source_file.read() + source_file.close() + yield (source_path, source) + def eraseFile( path ): file( path, 'wt').close() @@ -114,3 +122,7 @@ for zip_path in zip_files: print 'Analysing', zip_path self.runProjectTests( zip_path, zipFileSourceProdiver( zip_path ), result_dir ) + + def runFileSystemProject( self, result_dir, project_dir ): + print 'Processing', project_dir + self.runProjectTests( project_dir, fileSystemSourceProvider( project_dir ), result_dir ) Modified: rfta/trunk/test/testresultbrowser.py =================================================================== --- rfta/trunk/test/testresultbrowser.py 2007-04-15 21:36:02 UTC (rev 17) +++ rfta/trunk/test/testresultbrowser.py 2007-04-15 22:40:17 UTC (rev 18) @@ -29,7 +29,9 @@ TESTDATA_PATH = '../testdata' TESTDATA_PROJECTS_PATH = os.path.join( TESTDATA_PATH, 'projects' ) -TESTRESULT_PATH = '../testresult' +TESTRESULT_PATH = '../testresult/parser_projects' +##TESTRESULT_LEXER_PATH = '../testresult' +##TESTRESULT_PARSER_PATH = '../testresult' PATH = '' PORT = 8666 @@ -75,7 +77,7 @@ def __init__( self, project ): self.project = project base_path = os.path.join( TESTRESULT_PATH, project ) - self.decls = file( base_path + '-decl.txt', 'rt' ).read().split('\n') + self.decls = file( base_path + '-parser.txt', 'rt' ).read().split('\n') self.logs = {} current_path = None for line in file( base_path + '-log.txt', 'rt' ): @@ -186,7 +188,7 @@ def _makeIndex( self ): print '_makeIndex' - suffix = '-decl.txt' + suffix = '-parser.txt' s = "<table><tr><td>Project</td><td>%ok</td><td>Pass/Fail</td><td>Decl.</td></tr>" for path in glob.glob( os.path.join( TESTRESULT_PATH, '*' + suffix ) ): print 'Generating content for', path Property changes on: rfta/trunk/testresult/parser_unittests ___________________________________________________________________ Name: svn:ignore + *.txt This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-15 21:36:23
|
Revision: 17 http://rfta.svn.sourceforge.net/rfta/?rev=17&view=rev Author: blep Date: 2007-04-15 14:36:02 -0700 (Sun, 15 Apr 2007) Log Message: ----------- - added tests for parser Modified Paths: -------------- rfta/trunk/test/rftalexer_test.py rfta/trunk/test/rftatest.py Added Paths: ----------- rfta/trunk/test/rftaparser_test.py Property Changed: ---------------- rfta/trunk/test/ rfta/trunk/testresult/parser_projects/ Property changes on: rfta/trunk/test ___________________________________________________________________ Name: svn:ignore + *.pyc Modified: rfta/trunk/test/rftalexer_test.py =================================================================== --- rfta/trunk/test/rftalexer_test.py 2007-04-15 20:41:24 UTC (rev 16) +++ rfta/trunk/test/rftalexer_test.py 2007-04-15 21:36:02 UTC (rev 17) @@ -19,9 +19,9 @@ LEXER_PATH = r'..\build\test_rftalexer_Release\test_rftalexer.exe' if __name__ == '__main__': - zip_files = glob.glob( os.path.join( rftatest.TESTDATA_PROJECTS_DIR, '*.zip' ) ) - for zip_file in zip_files: - print 'Analysing', zip_file - source_provider = rftatest.zipFileSourceProdiver( zip_file ) - rftatest.runProjectTests( zip_file, source_provider, RESULT_DIR, rftatest.runTest, LEXER_PATH, - extra_flags = ('--no-output',) ) + class LexerTestRunner(rftatest.TestRunner): + def __init__( self ): + rftatest.TestRunner.__init__( self, LEXER_PATH, extra_flags = ('--no-output',) ) + self.output_file_suffix = '-lexer.txt' + + LexerTestRunner().runZippedProjects( RESULT_DIR ) Added: rfta/trunk/test/rftaparser_test.py =================================================================== --- rfta/trunk/test/rftaparser_test.py (rev 0) +++ rfta/trunk/test/rftaparser_test.py 2007-04-15 21:36:02 UTC (rev 17) @@ -0,0 +1,26 @@ +# Iterates over all the zipped source files contained in the ROOT/testdata directory +# and parser them with RFTA parser. +# Processing output for each zip archive is in XYZ-EXT.txt files, where XYZ +# is the zip file basename without extension, and where EXT is: +# -log: log generated by the lexer (errors detail). +# -status: indicates if an occurred for each files +# -parser: parser declaration dump for all parsed file of the archive +# +# Results can be browsed using the testresultbrowser.py script. + +# Requires python 2.4 (due to subprocess module) + +import glob +import os.path +import rftatest + +RESULT_DIR = os.path.join( rftatest.TESTRESULT_DIR, 'parser_projects' ) +PARSER_PATH = r'..\build\test_rftaparser_Release\test_rftaparser.exe' + +if __name__ == '__main__': + class ParserTestRunner(rftatest.TestRunner): + def __init__( self ): + rftatest.TestRunner.__init__( self, PARSER_PATH ) + self.output_file_suffix = '-parser.txt' + + ParserTestRunner().runZippedProjects( RESULT_DIR ) Modified: rfta/trunk/test/rftatest.py =================================================================== --- rfta/trunk/test/rftatest.py 2007-04-15 20:41:24 UTC (rev 16) +++ rfta/trunk/test/rftatest.py 2007-04-15 21:36:02 UTC (rev 17) @@ -6,7 +6,11 @@ import os import subprocess +TESTDATA_DIR = '../testdata' +TESTDATA_PROJECTS_DIR = os.path.join( TESTDATA_DIR, 'projects' ) +TESTRESULT_DIR = '../testresult' + def isSourceFile( path ): ext = os.path.splitext( path )[1] return ext.lower() in ('.h', '.hpp', '.c', '.cpp', '.cc', '.cxx' ) @@ -92,6 +96,21 @@ test_runner( source, source_path, log_path, output_path, exe_path, status_file, **test_runner_kwargs ) status_file.close() -TESTDATA_DIR = '../testdata' -TESTDATA_PROJECTS_DIR = os.path.join( TESTDATA_DIR, 'projects' ) -TESTRESULT_DIR = '../testresult' +class TestRunner: + def __init__( self, exe_path, **runner_kwargs ): + self.exe_path = exe_path + self.test_runner_kwargs = runner_kwargs + self.test_runner = runTest + self.log_file_suffix = '-log.txt' + self.output_file_suffix = '-lexer.txt' + self.keep_output = False + + def runProjectTests( self, project_name, source_provider, result_dir ): + return runProjectTests( project_name, source_provider, result_dir, self.test_runner, + self.exe_path, **self.test_runner_kwargs ) + + def runZippedProjects( self, result_dir, zip_dir = TESTDATA_PROJECTS_DIR ): + zip_files = glob.glob( os.path.join( zip_dir, '*.zip' ) ) + for zip_path in zip_files: + print 'Analysing', zip_path + self.runProjectTests( zip_path, zipFileSourceProdiver( zip_path ), result_dir ) Property changes on: rfta/trunk/testresult/parser_projects ___________________________________________________________________ Name: svn:ignore + *.txt This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-15 20:41:26
|
Revision: 16 http://rfta.svn.sourceforge.net/rfta/?rev=16&view=rev Author: blep Date: 2007-04-15 13:41:24 -0700 (Sun, 15 Apr 2007) Log Message: ----------- - refactored tests somewhat Modified Paths: -------------- rfta/trunk/src/test_rftalexer/main.cpp rfta/trunk/src/test_rftaparser/main.cpp rfta/trunk/test/rftalexer_test.py Added Paths: ----------- rfta/trunk/test/rftatest.py rfta/trunk/testresult/lexer_projects/ rfta/trunk/testresult/parser_projects/ Modified: rfta/trunk/src/test_rftalexer/main.cpp =================================================================== --- rfta/trunk/src/test_rftalexer/main.cpp 2007-04-15 14:30:53 UTC (rev 15) +++ rfta/trunk/src/test_rftalexer/main.cpp 2007-04-15 20:41:24 UTC (rev 16) @@ -58,6 +58,10 @@ failed_ = true; } } + else + { + handle_ = 0; + } } ~OutputFileHandle() @@ -138,30 +142,37 @@ Rfta::TokenId token = scanner.nextToken(); if ( token == Rfta::T_EOF ) { - fprintf( foutput, "%s\n", Rfta::tokenText(token) ); + if ( foutput ) + fprintf( foutput, "%s\n", Rfta::tokenText(token) ); break; } Rfta::Scanner::TokenTextRange textRange = scanner.lastTokenTextRange(); - fprintf( foutput, "%s %s\n", - Rfta::tokenText(token), - CppTL::quoteStringRange(textRange.first,textRange.second).c_str() ); - if ( token == Rfta::T_UNKNOWN ) + if ( foutput ) { - unknownTokenFound = true; - Rfta::Scanner::TokenRange range = scanner.lastTokenRange(); - int line = std::count( input.begin(), input.begin() + range.first, '\n' ); - int lastEOLIndex = CPPTL_MAX( 0, int(input.rfind( '\n', range.first )) ); - int column = range.first - lastEOLIndex; - int nextEOLIndex = CPPTL_MIN( input.find( '\n', range.first ), - input.length() ); - fprintf( flog, "-> Unknown token line %d column %d: %s %s\n", - line+1, column+1, + fprintf( foutput, "%s %s\n", Rfta::tokenText(token), CppTL::quoteStringRange(textRange.first,textRange.second).c_str() ); - fprintf( flog, "Line on failure:\n%s\n", - input.substr( lastEOLIndex, - nextEOLIndex - lastEOLIndex ).c_str() ); } + if ( token == Rfta::T_UNKNOWN ) + { + unknownTokenFound = true; + if ( foutput ) + { + Rfta::Scanner::TokenRange range = scanner.lastTokenRange(); + int line = std::count( input.begin(), input.begin() + range.first, '\n' ); + int lastEOLIndex = CPPTL_MAX( 0, int(input.rfind( '\n', range.first )) ); + int column = range.first - lastEOLIndex; + int nextEOLIndex = CPPTL_MIN( input.find( '\n', range.first ), + input.length() ); + fprintf( flog, "-> Unknown token line %d column %d: %s %s\n", + line+1, column+1, + Rfta::tokenText(token), + CppTL::quoteStringRange(textRange.first,textRange.second).c_str() ); + fprintf( flog, "Line on failure:\n%s\n", + input.substr( lastEOLIndex, + nextEOLIndex - lastEOLIndex ).c_str() ); + } + } } return unknownTokenFound ? 2 : 0; Modified: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp 2007-04-15 14:30:53 UTC (rev 15) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-15 20:41:24 UTC (rev 16) @@ -61,6 +61,10 @@ failed_ = true; } } + else + { + handle_ = 0; + } } ~OutputFileHandle() Modified: rfta/trunk/test/rftalexer_test.py =================================================================== --- rfta/trunk/test/rftalexer_test.py 2007-04-15 14:30:53 UTC (rev 15) +++ rfta/trunk/test/rftalexer_test.py 2007-04-15 20:41:24 UTC (rev 16) @@ -10,76 +10,18 @@ # Requires python 2.4 (due to subprocess module) -import zipfile import glob import os.path -import os -import subprocess +import rftatest -def isSourceFile( path ): - ext = os.path.splitext( path )[1] - return ext.lower() in ('.h', '.hpp', '.c', '.cpp', '.cc', '.cxx' ) -TESTDATA_DIR = '../testdata' -TESTDATA_PROJECTS_DIR = os.path.join( TESTDATA_DIR, 'projects' ) -RESULT_DIR = '../testresult' +RESULT_DIR = os.path.join( rftatest.TESTRESULT_DIR, 'lexer_projects' ) LEXER_PATH = r'..\build\test_rftalexer_Release\test_rftalexer.exe' -def appendToLog( outfile_log, text ): - if text: - log = file( outfile_log, 'a+t' ) - print >> log, text - log.close() - if __name__ == '__main__': - zip_files = glob.glob( os.path.join( TESTDATA_PROJECTS_DIR, '*.zip' ) ) + zip_files = glob.glob( os.path.join( rftatest.TESTDATA_PROJECTS_DIR, '*.zip' ) ) for zip_file in zip_files: - print zip_file - archive = zipfile.ZipFile( zip_file, 'r' ) print 'Analysing', zip_file - out_basepath = os.path.join( RESULT_DIR, os.path.split( os.path.splitext(zip_file)[0] )[1] ) - outfile_status = file( out_basepath + '-status.txt', 'wt' ) - outfile_log = out_basepath + '-log.txt' - file( outfile_log, 'wt').close() # clear log file -# outfile_decl = out_basepath + '-decl.txt' - outfile_lexer = out_basepath + '-lexer.txt' - outfile = file( out_basepath + '-decl.txt', 'wt') - outfile.close() - for info in archive.infolist(): - if isSourceFile( info.filename ): - source_path = info.filename - source = archive.read( source_path ) - print 'Parsing', source_path - appendToLog( outfile_log, "#SOURCELOG: " + source_path ) - cmd = ( LEXER_PATH, '-o', outfile_lexer, '-l', outfile_log, '--log-append' ) - try: -## print 'Running', cmd - process = subprocess.Popen( cmd, - stdin = subprocess.PIPE, - stdout = subprocess.PIPE, - stderr = subprocess.STDOUT ) - (process_stdout, process_stderr) = process.communicate( source ) - return_code = process.wait() - if return_code == 0: - print >> outfile_status, source_path, 'OK', '_' - else: - print >> outfile_status, source_path, 'FAILED', return_code - if process_stdout: - appendToLog( outfile_log, process_stdout ) - if process_stderr and process_stderr != process_stdout: - appendToLog( outfile_log, process_stderr ) - except OSError, e: - print >> outfile_status, source_path, 'FAILED', return_code - appendToLog( outfile_log, 'TestRunner => failed to spawn process:' ) - appendToLog( outfile_log, e ) -## cmd = '%s -o%s -l%s' % (LEXER_PATH,outfile_lexer,outfile_log) -## print cmd -## pipe = os.popen( cmd, 'w' ) -## pipe.write( source ) -## status = pipe.close() -## if status is None: -## print >> outfile_status, source_path, 'OK', '_' -## else: -## print >> outfile_status, source_path, 'FAILED', status - outfile_status.close() - outfile.close() + source_provider = rftatest.zipFileSourceProdiver( zip_file ) + rftatest.runProjectTests( zip_file, source_provider, RESULT_DIR, rftatest.runTest, LEXER_PATH, + extra_flags = ('--no-output',) ) Added: rfta/trunk/test/rftatest.py =================================================================== --- rfta/trunk/test/rftatest.py (rev 0) +++ rfta/trunk/test/rftatest.py 2007-04-15 20:41:24 UTC (rev 16) @@ -0,0 +1,97 @@ +# Requires python 2.4 (due to subprocess module) + +import zipfile +import glob +import os.path +import os +import subprocess + + +def isSourceFile( path ): + ext = os.path.splitext( path )[1] + return ext.lower() in ('.h', '.hpp', '.c', '.cpp', '.cc', '.cxx' ) + +def zipFileSourceProdiver( zip_path, is_source_file_pred = isSourceFile ): + archive = zipfile.ZipFile( zip_path, 'r' ) + for info in archive.infolist(): + if is_source_file_pred( info.filename ): + source_path = info.filename + source = archive.read( source_path ) + yield (source_path, source) + +def eraseFile( path ): + file( path, 'wt').close() + +def appendToFile( path, text ): + if text: + log = file( path, 'a+t' ) + print >> log, text + log.close() + +def runTest( source, + source_path, + log_path, + output_path, + exe_path, + status_file, + append_to_log = 'True', + append_to_output = 'True', + extra_flags = () ): + cmd = ( exe_path, '-o', output_path, '-l', log_path ) + if append_to_log: + cmd += ('--log-append', ) + if append_to_output: + cmd += ('--output-append', ) + cmd += extra_flags + try: + print 'Running', cmd + return_code = 1 + process = subprocess.Popen( cmd, + stdin = subprocess.PIPE, + stdout = subprocess.PIPE, + stderr = subprocess.STDOUT ) + (process_stdout, process_stderr) = process.communicate( source ) + return_code = process.wait() + if return_code == 0: + print >> status_file, source_path, 'OK', '_' + else: + print >> status_file, source_path, 'FAILED', return_code + if process_stdout: + appendToFile( log_path, process_stdout ) + if process_stderr and process_stderr != process_stdout: + appendToFile( log_path, process_stderr ) + return True + except IOError, e: + print >> status_file, source_path, 'FAILED', return_code + appendToFile( log_path, 'TestRunner => failed to spawn process (IOError):' ) + appendToFile( log_path, e ) + print e + return False + except OSError, e: + print >> status_file, source_path, 'FAILED', return_code + appendToFile( log_path, 'TestRunner => failed to spawn process:' ) + appendToFile( log_path, e ) + return False + + +def runProjectTests( project_name, + source_provider, + result_dir, + test_runner, + exe_path, + **test_runner_kwargs ): + out_basepath = os.path.join( result_dir, os.path.split( os.path.splitext(project_name)[0] )[1] ) + status_file = file( out_basepath + '-status.txt', 'wt' ) + log_path = out_basepath + '-log.txt' + output_path = out_basepath + '-parser.txt' + eraseFile( log_path ) + eraseFile( output_path ) + for source_path, source in source_provider: + print 'Processing', source_path + appendToFile( log_path, "#SOURCELOG: " + source_path ) + test_runner( source, source_path, log_path, output_path, exe_path, status_file, **test_runner_kwargs ) + status_file.close() + +TESTDATA_DIR = '../testdata' +TESTDATA_PROJECTS_DIR = os.path.join( TESTDATA_DIR, 'projects' ) +TESTRESULT_DIR = '../testresult' Property changes on: rfta/trunk/testresult/lexer_projects ___________________________________________________________________ Name: svn:ignore + *.txt This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-15 14:50:05
|
Revision: 15 http://rfta.svn.sourceforge.net/rfta/?rev=15&view=rev Author: blep Date: 2007-04-15 07:30:53 -0700 (Sun, 15 Apr 2007) Log Message: ----------- - fixed bug in quoteMultiLineString - error are now logged in the output and program status indicate if any error was found Modified Paths: -------------- rfta/trunk/include/cpptl/enumerator.h rfta/trunk/include/cpptl/stringtools.h rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/src/test_rftaparser/main.cpp Added Paths: ----------- rfta/trunk/testdata/cxxparser_ut/t_enum_001_empty.cpp rfta/trunk/testdata/cxxparser_ut/t_enum_002_empty_anonymous.cpp rfta/trunk/testdata/cxxparser_ut/t_ns_001_empty.cpp rfta/trunk/testdata/cxxparser_ut/t_ns_002_nested.cpp rfta/trunk/testdata/cxxparser_ut/t_transunit_empty.cpp rfta/trunk/testdata/cxxparser_ut/t_transunit_error.cpp Removed Paths: ------------- rfta/trunk/testdata/cxxparser_ut/t000000_empty.cpp rfta/trunk/testdata/cxxparser_ut/t001000_ns_empty.cpp rfta/trunk/testdata/cxxparser_ut/t001001_ns_nested.cpp rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty.cpp rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty_anonymous.cpp Property Changed: ---------------- rfta/trunk/makefiles/vs8/ Modified: rfta/trunk/include/cpptl/enumerator.h =================================================================== --- rfta/trunk/include/cpptl/enumerator.h 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/include/cpptl/enumerator.h 2007-04-15 14:30:53 UTC (rev 15) @@ -4,7 +4,11 @@ # include <cpptl/typetraits.h> # include <stdexcept> + /* Notes: figure out how to tweak thing so that it is possible to + pass either Type<> or an Enumerator as type target for any...() functions. + */ + #define CPPTL_ENUMERATOR_CHECK_CURRENT \ CPPTL_ASSERT_MESSAGE( is_open(), \ "Attempt to access current element on closed enumerator." ) Modified: rfta/trunk/include/cpptl/stringtools.h =================================================================== --- rfta/trunk/include/cpptl/stringtools.h 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/include/cpptl/stringtools.h 2007-04-15 14:30:53 UTC (rev 15) @@ -319,7 +319,7 @@ quoteString( const CppTL::ConstString &text, const char *newLineEscape = "\\n" ) { - return quoteStringRange( text.c_str(), text.c_str() + text.length() ); + return quoteStringRange( text.c_str(), text.c_str() + text.length(), newLineEscape ); } Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-15 14:30:53 UTC (rev 15) @@ -4,15 +4,32 @@ # include "cxxparser.h" # include "cxxtype.h" # include <cpptl/stack.h> +# include <deque> namespace Rfta { +class ErrorInfo +{ +public: + ErrorInfo( TextPos start, TextPos end, const CppTL::ConstString &message ); + CppTL::ConstString message_; + TextPos start_; + TextPos end_; +}; + +typedef CppTL::AnyEnumerator<const ErrorInfo &> EnumErrorInfo; + class CxxParserAction : public CxxParserDelegate { public: - CxxParserAction( DeclarationManager &declManager ); + CxxParserAction( DeclarationManager &declManager, + TokenContentManager &contentManager ); + bool hasError() const; + + EnumErrorInfo enumErrors() const; + public: // overridden from CxxParserDelegate virtual void declareAndEnterNamespace(const TokenScannerPosRange &id); virtual void exitNamespaceDeclaration(); @@ -20,8 +37,13 @@ virtual void handleStatementError(const TokenScannerPosRange &error_tokens); private: + void addError( const TokenScannerPosRange &tokens, + const char *message ); + DeclarationManager &decls_; CppTL::Stack<NamespaceScope *> namespaceScopes_; + std::deque<ErrorInfo> errors_; + TokenContentManager &contentManager_; //ScopeManager scopeManager_; }; Property changes on: rfta/trunk/makefiles/vs8 ___________________________________________________________________ Name: svn:ignore - rfta.ncb + rfta.ncb *.log *.out Modified: rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user =================================================================== --- rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user 2007-04-15 14:30:53 UTC (rev 15) @@ -11,7 +11,7 @@ <DebugSettings Command="$(TargetPath)" WorkingDirectory="" - CommandArguments="../../testdata/cxxparser_ut/t001001_ns_nested.cpp" + CommandArguments="../../testdata/cxxparser_ut/t_transunit_error.cpp" Attach="false" DebuggerType="3" Remote="1" Modified: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -5,17 +5,45 @@ // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +// class ErrorInfo +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +ErrorInfo::ErrorInfo( TextPos start, TextPos end, const CppTL::ConstString &message ) + : start_( start ) + , end_( end ) + , message_( message ) +{ +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// // class CxxParserAction // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -CxxParserAction::CxxParserAction( DeclarationManager &declManager ) +CxxParserAction::CxxParserAction( DeclarationManager &declManager, + TokenContentManager &contentManager ) : decls_( declManager ) + , contentManager_( contentManager ) { namespaceScopes_.push( &declManager.getGlobalNamespaceScope() ); } +bool +CxxParserAction::hasError() const +{ + return !errors_.empty(); +} + +EnumErrorInfo +CxxParserAction::enumErrors() const +{ + return CppTL::Enum::anyContainer( errors_, CppTL::Type<const ErrorInfo &>() ); +} + + void CxxParserAction::declareAndEnterNamespace(const TokenScannerPosRange &id) { @@ -33,14 +61,29 @@ void -CxxParserAction::handleDeclarationError(const TokenScannerPosRange &error_tokens) +CxxParserAction::handleDeclarationError(const TokenScannerPosRange &tokens) { + addError( tokens, "Error in declaration" ); } void -CxxParserAction::handleStatementError(const TokenScannerPosRange &error_tokens) +CxxParserAction::handleStatementError(const TokenScannerPosRange &tokens) { + addError( tokens, "Error in statement" ); } + +void +CxxParserAction::addError( const TokenScannerPosRange &tokens, + const char *message ) +{ + TokenScannerPos lastToken = tokens.start_; + if ( tokens.end_ != tokens.start_ ) + lastToken = tokens.end_ -1; + TextPos startPos = tokens.start_->pos_; + TextPos endPos = lastToken->pos_ + contentManager_.getTokenText(*lastToken).length(); + errors_.push_front( ErrorInfo( startPos, endPos, message ) ); +} + } // namespace Rfta { Modified: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -84,18 +84,34 @@ bool failed_; }; + + class DeclarationDumper : public Rfta::ScopeVisitor { public: DeclarationDumper( FILE *fout, Rfta::DeclarationManager &declarationManager, - Rfta::TokenContentManager &contentManager ) + Rfta::TokenContentManager &contentManager, + const std::string &input ) : fout_( fout ) , decls_( declarationManager ) , contentManager_( contentManager ) + , input_( input ) { } + void printErrors( Rfta::EnumErrorInfo enumErrors ) + { + while ( enumErrors.hasNext() ) + { + const Rfta::ErrorInfo &error = enumErrors.next(); + std::string msg = input_.substr( error.start_, error.end_ ); + fprintf( fout_, "#=> Error: %s\n%s\n", + error.message_.c_str(), + CppTL::quoteMultiLineString( msg ).c_str() ); + } + } + void visitGlobalNamespaceScope( Rfta::GlobalNamespaceScope &scope ) { printScopeHeader( "namespace", "<GlobalNamespace>" ); @@ -140,6 +156,7 @@ Rfta::DeclarationManager &decls_; Rfta::TokenContentManager &contentManager_; std::string indent_; + const std::string &input_; }; @@ -211,14 +228,20 @@ break; } Rfta::DeclarationManager declarationManager; - parser.setDelegate( *new Rfta::CxxParserAction( declarationManager ) ); + Rfta::CxxParserAction *parserAction = new Rfta::CxxParserAction( declarationManager, + contentManager ); + parser.setDelegate( *parserAction ); parser.initialize( tokens ); bool matched = parser.match_translation_unit(); if ( foutput ) { - DeclarationDumper dumper( foutput, declarationManager, contentManager ); + DeclarationDumper dumper( foutput, declarationManager, contentManager, input ); dumper.visitGlobalNamespaceScope( declarationManager.getGlobalNamespaceScope() ); + if ( parserAction->hasError() ) + dumper.printErrors( parserAction->enumErrors() ); } - return matched; + if ( !matched || parserAction->hasError() ) + return 2; + return 0; } Deleted: rfta/trunk/testdata/cxxparser_ut/t000000_empty.cpp =================================================================== Deleted: rfta/trunk/testdata/cxxparser_ut/t001000_ns_empty.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t001000_ns_empty.cpp 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/testdata/cxxparser_ut/t001000_ns_empty.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -1,3 +0,0 @@ -namespace Test -{ -} Deleted: rfta/trunk/testdata/cxxparser_ut/t001001_ns_nested.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t001001_ns_nested.cpp 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/testdata/cxxparser_ut/t001001_ns_nested.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -1,6 +0,0 @@ -namespace Test -{ - namespace Test2 - { - } -} Deleted: rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty.cpp 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -1,3 +0,0 @@ -enum T002000_E1 -{ -}; Deleted: rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty_anonymous.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty_anonymous.cpp 2007-04-15 11:08:32 UTC (rev 14) +++ rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty_anonymous.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -1,3 +0,0 @@ -enum -{ -}; Added: rfta/trunk/testdata/cxxparser_ut/t_enum_001_empty.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_enum_001_empty.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_enum_001_empty.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -0,0 +1,3 @@ +enum T002000_E1 +{ +}; Added: rfta/trunk/testdata/cxxparser_ut/t_enum_002_empty_anonymous.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_enum_002_empty_anonymous.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_enum_002_empty_anonymous.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -0,0 +1,3 @@ +enum +{ +}; Added: rfta/trunk/testdata/cxxparser_ut/t_ns_001_empty.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_ns_001_empty.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_ns_001_empty.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -0,0 +1,3 @@ +namespace Test +{ +} Added: rfta/trunk/testdata/cxxparser_ut/t_ns_002_nested.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_ns_002_nested.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_ns_002_nested.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -0,0 +1,6 @@ +namespace Test +{ + namespace Test2 + { + } +} Added: rfta/trunk/testdata/cxxparser_ut/t_transunit_empty.cpp =================================================================== Added: rfta/trunk/testdata/cxxparser_ut/t_transunit_error.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t_transunit_error.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t_transunit_error.cpp 2007-04-15 14:30:53 UTC (rev 15) @@ -0,0 +1,3 @@ +namespace +namespace namespace +namespace This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-15 11:08:34
|
Revision: 14 http://rfta.svn.sourceforge.net/rfta/?rev=14&view=rev Author: blep Date: 2007-04-15 04:08:32 -0700 (Sun, 15 Apr 2007) Log Message: ----------- - fixed bugs in IntrusiveSList - parser now output list of found namespaces. Modified Paths: -------------- rfta/trunk/include/cpptl/intrusiveslist.h rfta/trunk/include/rfta/cxxparserbase.h rfta/trunk/include/rfta/cxxtype.h rfta/trunk/include/rfta/forwards.h rfta/trunk/include/rfta/token.h rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj rfta/trunk/makefiles/vs8/rfta.suo rfta/trunk/src/lib_rftaparser/cxxtype.cpp rfta/trunk/src/test_rftaparser/main.cpp Property Changed: ---------------- rfta/trunk/testdata/projects/ rfta/trunk/testresult/ Modified: rfta/trunk/include/cpptl/intrusiveslist.h =================================================================== --- rfta/trunk/include/cpptl/intrusiveslist.h 2007-04-14 22:49:12 UTC (rev 13) +++ rfta/trunk/include/cpptl/intrusiveslist.h 2007-04-15 11:08:32 UTC (rev 14) @@ -25,9 +25,6 @@ ~IntrusiveSList() { -#ifndef NDEBUG - clear(); -#endif } bool empty() const @@ -37,15 +34,6 @@ void clear() { -#ifndef NDEBUG - Object *current = head_; - while ( current ) - { - Object *objectToClean = current; - current = chainedNext( *current ); - chainedNext( *objectToClean ) =0; - } -#endif head_ = 0; } @@ -61,19 +49,16 @@ void push_front( const Object &object ) { - Object *&prevObject = chainedNext(object); - // Notes: this assertion is only true in debug mode - // For optimization, pointer are not reseted when element are removed from list. - CPPTL_ASSERT_MESSAGE( prevObject == 0, "Attempting to insert an object already in a list." ); + const Object *&prevObject = chainedNext(object); prevObject = head_; - head_ = prevObject; + head_ = &object; } void pop_front() { CPPTL_ASSERT_MESSAGE( head_ != 0, "Can not pop front element of an empty list." ); #ifndef NDEBUG - Object *objectToClean = head_; + const Object *objectToClean = head_; head_ = chainedNext(head_); chainedNext( objectToClean ) =0; #else @@ -94,11 +79,10 @@ } private: - static inline Object *&chainedNext( const Object &object ) + static inline const Object *&chainedNext( const Object &object ) { - Object *theObject = (Object *)&object; - uint8_t *pObject = (uint8_t *)( theObject ); - return *reinterpret_cast<Object **>( pObject + nextOffset ); + uint8_t *pObject = (uint8_t *)( &object ); + return *reinterpret_cast<const Object **>( pObject + nextOffset ); } template<typename Value,typename Object> @@ -107,7 +91,7 @@ public: typedef Value &value_type; - SListThinEnum( Object *head ) + SListThinEnum( const Object *head ) : current_( head ) { } @@ -120,22 +104,22 @@ Value ¤t() const { CPPTL_ENUMERATOR_CHECK_CURRENT; - return *current_; + return (Value &)*current_; } void advance() { CPPTL_ENUMERATOR_CHECK_ADVANCE; - current_ = chainedNext(current_); + current_ = chainedNext(*current_); } private: - Object *current_; + const Object *current_; }; template<typename Object,typename ObjectType> friend class SListThinEnum; - Object *head_; + const Object *head_; }; } // namespace CppTL { Modified: rfta/trunk/include/rfta/cxxparserbase.h =================================================================== --- rfta/trunk/include/rfta/cxxparserbase.h 2007-04-14 22:49:12 UTC (rev 13) +++ rfta/trunk/include/rfta/cxxparserbase.h 2007-04-15 11:08:32 UTC (rev 14) @@ -1,7 +1,8 @@ #ifndef RFTA_PARSER_CXXPARSERBASE_H_INCLUDED # define RFTA_PARSER_CXXPARSERBASE_H_INCLUDED -# include <rfta/token.h> +# include "forwards.h" +# include "token.h" # include <cpptl/conststring.h> # include <vector> # include <assert.h> Modified: rfta/trunk/include/rfta/cxxtype.h =================================================================== --- rfta/trunk/include/rfta/cxxtype.h 2007-04-14 22:49:12 UTC (rev 13) +++ rfta/trunk/include/rfta/cxxtype.h 2007-04-15 11:08:32 UTC (rev 14) @@ -35,12 +35,28 @@ //typedef Impl::PhantomNamespaceId *NamespaceId; //typedef Impl::PhantomEnumId *EnumId; + +class ScopeVisitor +{ +public: + virtual ~ScopeVisitor() + { + } + + virtual void visitGlobalNamespaceScope( GlobalNamespaceScope &scope ) = 0; + virtual void visitAnonymousNamespaceScope( AnonymousNamespaceScope &scope ) = 0; + virtual void visitNamespaceDecl( NamespaceDecl &scope ) = 0; +}; + + class Scope { public: Scope(); virtual ~Scope(); + virtual void accept( ScopeVisitor &visitor ) = 0; + private: Scope( const Scope &other ); Scope &operator =( const Scope &other ); @@ -68,6 +84,7 @@ { public: void addNamespace( NamespaceScope &scope ); + void visitChildScope( ScopeVisitor &visitor ); private: // typedef CppTL::GrowHashMap<TextId, Declaration *> DeclarationsByName; @@ -78,13 +95,17 @@ class GlobalNamespaceScope : public NamespaceScope { -public: +public: // overridden from NamespaceScope + virtual void accept( ScopeVisitor &visitor ); + }; class AnonymousNamespaceScope : public NamespaceScope { -public: +public: // overridden from NamespaceScope + virtual void accept( ScopeVisitor &visitor ); + }; @@ -95,6 +116,11 @@ NamespaceDecl( const LocatedSymbol &id, NamespaceScope &parentScope ); + const LocatedSymbol &getSymbol() const; + +public: // overridden from NamespaceScope + virtual void accept( ScopeVisitor &visitor ); + private: LocatedSymbol id_; NamespaceScope &parentScope_; Modified: rfta/trunk/include/rfta/forwards.h =================================================================== --- rfta/trunk/include/rfta/forwards.h 2007-04-14 22:49:12 UTC (rev 13) +++ rfta/trunk/include/rfta/forwards.h 2007-04-15 11:08:32 UTC (rev 14) @@ -14,8 +14,15 @@ class TextRepository; class TokenStream; -// cxxparseraction.h +// cxxtype.h +class AnonymousNamespaceScope; +class Declaration; class DeclarationManager; +class GlobalNamespaceScope; +class NamespaceDecl; +class NamespaceScope; +class Scope; +class ScopeVisitor; } // namespace Rfta { Modified: rfta/trunk/include/rfta/token.h =================================================================== --- rfta/trunk/include/rfta/token.h 2007-04-14 22:49:12 UTC (rev 13) +++ rfta/trunk/include/rfta/token.h 2007-04-15 11:08:32 UTC (rev 14) @@ -151,6 +151,11 @@ return repository_.getLiteralId( CppTL::ConstCharView(begin,end) ); } + const CppTL::ConstString &getSymbolText( const LocatedSymbol &symbol ) const + { + return repository_.getIdentifierText( symbol.text_ ); + } + CppTL::ConstString getTokenText( const Token &token ) const { switch ( getTokenStorageMethod(token.tokenId_) ) Modified: rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj =================================================================== --- rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj 2007-04-14 22:49:12 UTC (rev 13) +++ rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj 2007-04-15 11:08:32 UTC (rev 14) @@ -272,6 +272,10 @@ > </File> <File + RelativePath="..\..\include\cpptl\intrusiveslist.h" + > + </File> + <File RelativePath="..\..\include\cpptl\slist.h" > </File> Modified: rfta/trunk/makefiles/vs8/rfta.suo =================================================================== (Binary files differ) Modified: rfta/trunk/src/lib_rftaparser/cxxtype.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-14 22:49:12 UTC (rev 13) +++ rfta/trunk/src/lib_rftaparser/cxxtype.cpp 2007-04-15 11:08:32 UTC (rev 14) @@ -28,8 +28,19 @@ { scopes_.push_front( scope ); } - + +void +NamespaceScope::visitChildScope( ScopeVisitor &visitor ) +{ + ChildScopes::Enum enumerator = scopes_.enumItems(); + while ( enumerator.hasNext() ) + { + enumerator.next().accept( visitor ); + } +} + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class Declaration @@ -47,9 +58,35 @@ // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// +// class AnonymousNamespaceScope +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +void +AnonymousNamespaceScope::accept( ScopeVisitor &visitor ) +{ + visitor.visitAnonymousNamespaceScope( *this ); +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// // class NamespaceDecl // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// + +void +GlobalNamespaceScope::accept( ScopeVisitor &visitor ) +{ + visitor.visitGlobalNamespaceScope( *this ); +} + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class NamespaceDecl +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// NamespaceDecl::NamespaceDecl( const LocatedSymbol &id, NamespaceScope &parentScope ) : id_( id ) @@ -58,6 +95,21 @@ } +const LocatedSymbol & +NamespaceDecl::getSymbol() const +{ + return id_; +} + + +void +NamespaceDecl::accept( ScopeVisitor &visitor ) +{ + visitor.visitNamespaceDecl( *this ); +} + + + // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class DeclarationManager Modified: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp 2007-04-14 22:49:12 UTC (rev 13) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-15 11:08:32 UTC (rev 14) @@ -84,7 +84,66 @@ bool failed_; }; +class DeclarationDumper : public Rfta::ScopeVisitor +{ +public: + DeclarationDumper( FILE *fout, + Rfta::DeclarationManager &declarationManager, + Rfta::TokenContentManager &contentManager ) + : fout_( fout ) + , decls_( declarationManager ) + , contentManager_( contentManager ) + { + } + void visitGlobalNamespaceScope( Rfta::GlobalNamespaceScope &scope ) + { + printScopeHeader( "namespace", "<GlobalNamespace>" ); + scope.visitChildScope( *this ); + printScopeFooter(); + } + + void visitAnonymousNamespaceScope( Rfta::AnonymousNamespaceScope &scope ) + { + printScopeHeader( "namespace", "<anonymous>" ); + scope.visitChildScope( *this ); + printScopeFooter(); + } + + void visitNamespaceDecl( Rfta::NamespaceDecl &scope ) + { + printScopeHeader( "namespace", getSymbolText(scope.getSymbol()).c_str() ); + scope.visitChildScope( *this ); + printScopeFooter(); + } + +private: + CppTL::ConstString getSymbolText( const Rfta::LocatedSymbol &symbol ) const + { + return contentManager_.getSymbolText(symbol); + } + + void printScopeHeader( const std::string &type, const std::string &name ) + { + fprintf( fout_, "%s%s: %s {\n", indent_.c_str(), type.c_str(), name.c_str() ); + indent_ += " "; + } + + void printScopeFooter() + { + indent_.resize( indent_.length() - 3 ); + fprintf( fout_, "%s}\n", indent_.c_str() ); + } + +private: + FILE *fout_; + Rfta::DeclarationManager &decls_; + Rfta::TokenContentManager &contentManager_; + std::string indent_; +}; + + + int __cdecl main( int argc, const char *argv[] ) { std::string log; @@ -97,8 +156,8 @@ bool appendLog; bool appendOutput; Rfta::OptionsParser cmd; - cmd.addOption( 'l', "log", log, "lexer.log", "Set log path" ); - cmd.addOption( 'o', "output", output, "lexer.out", "Set output path" ); + cmd.addOption( 'l', "log", log, "parser.log", "Set log path" ); + cmd.addOption( 'o', "output", output, "parser.out", "Set output path" ); cmd.addEnableOption( 's', "silent", isSilent, "Disable logging & output generation" ); cmd.addOption( 'i', "input", file, "", "Set input path" ); cmd.addDisableOption( 0, "output", noOutput, "Disable output generation" ); @@ -155,6 +214,11 @@ parser.setDelegate( *new Rfta::CxxParserAction( declarationManager ) ); parser.initialize( tokens ); bool matched = parser.match_translation_unit(); + if ( foutput ) + { + DeclarationDumper dumper( foutput, declarationManager, contentManager ); + dumper.visitGlobalNamespaceScope( declarationManager.getGlobalNamespaceScope() ); + } return matched; } Property changes on: rfta/trunk/testdata/projects ___________________________________________________________________ Name: svn:ignore + *.zip Property changes on: rfta/trunk/testresult ___________________________________________________________________ Name: svn:ignore + *.txt This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-14 22:49:13
|
Revision: 13 http://rfta.svn.sourceforge.net/rfta/?rev=13&view=rev Author: blep Date: 2007-04-14 15:49:12 -0700 (Sat, 14 Apr 2007) Log Message: ----------- - started working on namespace parsing. - integrated some performance oriented container. Modified Paths: -------------- rfta/trunk/include/cpptl/config.h rfta/trunk/include/rfta/cpptokensid.h rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/include/rfta/forwards.h rfta/trunk/include/rfta/token.h rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj rfta/trunk/makefiles/vs8/rfta.suo rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/src/test_rftaparser/main.cpp Added Paths: ----------- rfta/trunk/include/cpptl/batchallocator.h rfta/trunk/include/cpptl/growhashtable.h rfta/trunk/include/cpptl/intrusiveslist.h rfta/trunk/include/cpptl/slist.h rfta/trunk/include/cpptl/stack.h rfta/trunk/include/rfta/cxxtype.h rfta/trunk/include/rfta/cxxtype_old.h rfta/trunk/src/lib_rftaparser/cxxtype.cpp rfta/trunk/src/lib_rftaparser/cxxtype_old.cpp Added: rfta/trunk/include/cpptl/batchallocator.h =================================================================== --- rfta/trunk/include/cpptl/batchallocator.h (rev 0) +++ rfta/trunk/include/cpptl/batchallocator.h 2007-04-14 22:49:12 UTC (rev 13) @@ -0,0 +1,211 @@ +#ifndef CPPTL_BATCHALLOCATOR_H_INCLUDED +# define CPPTL_BATCHALLOCATOR_H_INCLUDED + +# include <cpptl/config.h> +# include <stdlib.h> +# include <vector> + +namespace CppTL { + +/* Fast memory allocator. + * + * This memory allocator allocates memory for a batch of object (specified by + * the page size, the number of object in each page). + * + * It does not allow the destruction of a single object. All the allocated objects + * can be destroyed at once. The memory can be either released or reused for future + * allocation. + * + * The in-place new operator must be used to construct the object using the pointer + * returned by allocate. + * + * Example: + * \code + * BatchAllocator<CxxType> allocator; + * allocator.setPageSize( 10000 ); + * for ( int index =0; index < 1000000; ++index ) + * new (allocator.allocate()) CxxType( ... ); + * allocator.destructAllocatedObjects(); // destroy the object but reuse memory + * for ( int index =0; index < 1000000; ++index ) + * new (allocator.allocate()) CxxType( ... ); + * \endcode + */ +template<typename AllocatedType> +class BatchAllocator : public CppTL::NonCopyable +{ +public: + typedef AllocatedType AllocatedType; + + BatchAllocator( unsigned int objectsPerPage = 1024 ) + : objectsPerPage_( objectsPerPage ) + , freeHead_( 0 ) + { +// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); + CPPTL_ASSERT_MESSAGE( sizeof(AllocatedType) >= sizeof(AllocatedType *), + "AllocatedType is too small" ); // We must be able to store a slist in the object free space. + CPPTL_ASSERT_MESSAGE( objectsPerPage >= 16, "Must have at least 16 objects per page." ); + batches_ = allocateBatch( 0 ); + currentBatch_ = batches_; + } + + ~BatchAllocator() + { + reclaimMemory(); + free( batches_ ); // free the dummy head page. + } + + void setPageSize( unsigned int objectsPerPage ) + { + CPPTL_ASSERT_MESSAGE( objectsPerPage >= 16, "Must have at least 16 objects per page" ); + objectsPerPage_ = objectsPerPage; + } + + AllocatedType *allocate() + { + if ( freeHead_ ) + { + AllocatedType *object = freeHead_; + freeHead_ = *(AllocatedType **)object; + object->~AllocatedType(); // Makes sure its ready for construction. + // Notes: possible optimization if operator = is supported + return object; + } + if ( currentBatch_->used_ == currentBatch_->maxSize_ ) + { + currentBatch_ = currentBatch_->next_; + while ( currentBatch_ && currentBatch_->used_ == currentBatch_->maxSize_ ) + currentBatch_ = currentBatch_->next_; + + if ( !currentBatch_ ) // no free batch found, allocate a new one + { + currentBatch_ = allocateBatch( objectsPerPage_ ); + currentBatch_->next_ = batches_; // insert at the head of the list + batches_ = currentBatch_; + } + } + return ¤tBatch_->buffer_[currentBatch_->used_++]; + } + + /// Release the object. + /// @warning the object destructor is not called immediately. The object will be + /// destructed when it is reused for allocation. + void destruct( AllocatedType *object ) + { + CPPTL_ASSERT_MESSAGE( object != 0, "Invalid object (null)" ); + *(AllocatedType **)object = freeHead_; + freeHead_ = object; + } + + /// Destroys all allocated objects calling their destructor. + /// The memory is not freeed and is reused for future call to allocate() + void destructAllocatedObjects() + { + for ( BatchInfo *batch = batches_; batch; batch = batch->next_ ) + { + for ( unsigned int index =0; index < batch->used_; ++index ) + { + AllocatedType *object = &batch->buffer_[index]; + object->~AllocatedType(); + } + batch->used_ = 0; + } + currentBatch_ = batches_; + freeHead_ = 0; + } + + /// Destroys all allocated objects and free the allocated memory. + void reclaimMemory() + { + destructAllocatedObjects(); + for ( BatchInfo *batch = batches_; batch; ) + { + BatchInfo *nextBatch = batch->next_; + if ( batch->maxSize_ == 0 ) // preserve the dummy page + batches_ = batch; + else + free( batch ); + batch = nextBatch; + } + batches_->next_ = 0; + freeHead_ = 0; + currentBatch_ = batches_; + } + + void swap( BatchAllocator &other ) + { + CppTL::swap( batches_, other.batches_ ); + CppTL::swap( currentBatch_, other.currentBatch_ ); + CppTL::swap( objectsPerPage_, other.objectsPerPage_ ); + CppTL::swap( freeHead_, other.freeHead_ ); + } + +private: + struct BatchInfo + { + BatchInfo *next_; + unsigned int used_; + unsigned int maxSize_; + AllocatedType buffer_[1]; + }; + + static BatchInfo *allocateBatch( unsigned int objectsPerPage ) + { + unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType) + + sizeof(AllocatedType) * objectsPerPage; + BatchInfo *batch = (BatchInfo*)malloc( mallocSize ); + batch->next_ = 0; + batch->used_ = 0; + batch->maxSize_ = objectsPerPage; + return batch; + } + + BatchInfo *batches_; + BatchInfo *currentBatch_; + /// Head of a single linked list within the allocated space of freeed object + AllocatedType *freeHead_; + unsigned int objectsPerPage_; +}; + + + +template<typename Allocator> +class ProxyAllocator +{ +public: + typedef typename Allocator::AllocatedType AllocatedType; + typedef Allocator Allocator; + + ProxyAllocator( Allocator &allocator ) + : allocator_( &allocator ) + { + } + + void setPageSize( unsigned int objectsPerPage ) + { + allocator_->setPageSize( objectsPerPage ); + } + + AllocatedType *allocate() + { + return allocator_->allocate(); + } + + void destruct( AllocatedType *object ) + { + allocator_->destruct( object ); + } + + void swap( ProxyAllocator &other ) + { + CppTL::swap( allocator_, other.allocator_ ); + } + +private: + Allocator *allocator_; +}; + + +} // namespace CppTL { + +#endif // CPPTL_BATCHALLOCATOR_H_INCLUDED + Modified: rfta/trunk/include/cpptl/config.h =================================================================== --- rfta/trunk/include/cpptl/config.h 2007-04-13 07:56:03 UTC (rev 12) +++ rfta/trunk/include/cpptl/config.h 2007-04-14 22:49:12 UTC (rev 13) @@ -223,6 +223,12 @@ #endif namespace CppTL { + typedef unsigned char uint8_t; + typedef signed char int8_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef signed int int32_t; + typedef unsigned int uint32_t; // defines portable int64_t && uint64_t # ifndef CPPTL_NO_INT64 Added: rfta/trunk/include/cpptl/growhashtable.h =================================================================== --- rfta/trunk/include/cpptl/growhashtable.h (rev 0) +++ rfta/trunk/include/cpptl/growhashtable.h 2007-04-14 22:49:12 UTC (rev 13) @@ -0,0 +1,902 @@ +#ifndef CPPTL_GROWHASHTABLE_H_INCLUDED +# define CPPTL_GROWHASHTABLE_H_INCLUDED + +# include <cpptl/enumerator.h> +# include <cpptl/batchallocator.h> +# include <vector> +# include <functional> +# include <memory.h> + +# ifdef CPPTL_GROWHASTABLE_STATISTICS +# define CPPTL_GROWHASTABLE_STATISTICS_UPDATE( x ) x; +# else +# define CPPTL_GROWHASTABLE_STATISTICS_UPDATE( x ) +# endif + +namespace CppTL { + +template<typename Object> +struct DefaultHasher +{ + typedef Object HashKey; + HashKey operator()( Object object ) const + { + return object; + } +}; + +template<typename Object> +struct DefaultHasher<Object *> +{ + typedef unsigned int HashKey; + HashKey operator()( Object *object ) const + { + return (unsigned int)(object); + } +}; + +template<typename Object> +struct HashMethodHasher +{ + typedef typename Object::HashKey HashKey; + HashKey operator()( const Object &object ) const + { + return object.hash(); + } +}; + +template<typename Object> +struct GrowHashSetChainedObject +{ + GrowHashSetChainedObject( const Object &object, GrowHashSetChainedObject *next ) + : object_( object ) + , next_( next ) + { + } + Object object_; + GrowHashSetChainedObject *next_; +}; + +template< typename Key, typename Value > +struct Entry +{ + Entry() {} + Entry( const Key &key, const Value &value = Value() ) + : key_( key ), value_( value ) + { + } + + Key key_; + Value value_; +}; + + +template< typename Object > +struct GrowHashSetTraits +{ + typedef GrowHashSetChainedObject<Object> AllocatedType; +}; + +template< typename Key, typename Value> +struct GrowHashMapTraits +{ + typedef GrowHashSetChainedObject< Entry<Key,Value> > AllocatedType; +}; + + +/* Growing hash table + * This hash-table implementation offer the following features: + * - once inserted in the hash-table, the address of an object will always + * be the same, regardless of resizing. Object are obviously discarded on assignement. + * - on bucket resize, all objects are rehashed + * - equality predicate call (look-up key, existing entry) + */ +template<typename Object + ,typename Hasher=DefaultHasher<Object> + ,typename EqualPred=std::equal_to<Object> + ,typename LookUpKey=Object + ,typename Allocator=BatchAllocator< typename GrowHashSetTraits<Object>::AllocatedType > + > +class GrowHashSet +{ +public: + typedef unsigned int BucketIndex; + +# ifdef CPPTL_GROWHASTABLE_STATISTICS +# if CPPTL_NO_INT64 + typedef unsigned int StatisticCounter; +# else + typedef CppTL::uint64_t StatisticCounter; +# endif +# endif + class ThinHashSetEnum; + struct ThinHashSetEnumByValue; + + typedef CppTL::SugarEnumerator< ThinHashSetEnum, Object &> Enum; + typedef CppTL::TransformEnumerator< ThinHashSetEnumByValue, Enum> EnumByValue; + + typedef Allocator Allocator; + + GrowHashSet( BucketIndex initialBuckets = 7 ) + { + initialize( initialBuckets ); + } + + GrowHashSet( Allocator allocator, + BucketIndex initialBuckets = 7 ) + : allocator_( allocator ) + { + initialize( initialBuckets ); + } + + void initialize( BucketIndex initialBuckets ) + { + size_ = 0; + resizeThreshold_ = 0; +#ifdef CPPTL_GROWHASTABLE_STATISTICS + collisionCount_ = 0; + probeCount_ = 0; + containsQueryCount_ = 0; +#endif + if ( initialBuckets ) + resizeDelta( initialBuckets ); + } + + GrowHashSet( const GrowHashSet &other ) + : size_( 0 ) + , resizeThreshold_( 0 ) +#ifdef CPPTL_GROWHASTABLE_STATISTICS + , collisionCount_( 0 ) + , probeCount_( 0 ) + , containsQueryCount_( 0 ) +#endif + { + resizeDelta( other.size_ ); + for ( Buckets::const_iterator it = other.buckets_.begin(); + it != other.buckets_.end(); + ++it ) + { + for ( ChainedObject *current = *it; current; current = current->next_ ) + { + BucketIndex index = hasher_( current->object_ ) % buckets_.size(); + return addObjectToBucket( index, current->object_ ); + } + } + } + + ~GrowHashSet() + { + } + + GrowHashSet &operator =( const GrowHashSet &other ) + { + GrowHashSet temp( other ); + swap( temp ); + return *this; + } + + // Set the page size for the bucket entry page allocator. + void setPageSize( unsigned int objectsPerPage ) + { + allocator_.setPageSize( objectsPerPage ); + } + + BucketIndex size() const + { + return size_; + } + + bool empty() const + { + return size_ == 0; + } + + void setHasher( Hasher hasher ) + { + hasher_ = hasher; + } + + void setEqualPred( EqualPred equal ) + { + equal_ = equal; + } + + Enum enumItems() + { + return CppTL::Enum::sugar( ThinHashSetEnum( buckets_ ) ); + } + + EnumByValue enumItemsByValue() const + { + return CppTL::Enum::transform( CppTL::Enum::sugar( ThinHashSetEnum( buckets_ ) ), + ThinHashSetEnumByValue() ); + } + + void clear() + { + allocator_.destructAllocatedObjects(); + if ( !buckets_.empty() ) + memset( &buckets_[0], 0, buckets_.size() ); + } + + /// Safe insertion: search for duplicate and insert only if no duplicate found + Object &add( const Object &object, bool *isDuplicate = 0 ) + { + resizeDelta( 1 ); + BucketIndex index = hasher_( object ) % buckets_.size(); + for ( ChainedObject *current = buckets_[index]; current; current = current->next_ ) + { + CPPTL_GROWHASTABLE_STATISTICS_UPDATE( ++collisionCount_ ); + if ( equal_( object, current->object_ ) ) + { + if ( isDuplicate ) + *isDuplicate = true; + return current->object_; + } + } + if ( isDuplicate ) + *isDuplicate = false; + return addObjectToBucket( index, object ); + } + + /// Safe insertion: add or replace the existing entry. + Object &replace( const Object &object, bool *isDuplicate = 0 ) + { + bool duplicate; + Object *addedEntry = &add( object, &duplicate ); + if ( duplicate ) + *addedEntry = entry; + if ( isDuplicate ) + *isDuplicate = duplicate; + return addedEntry; + } + + /// Fast insertion, but insert the object even if it is a duplicate. + /// => the object is inserted at the head of the bucket linked list + /// @return reference on the inserted object. This address will never change. + Object &uncheckedAdd( const Object &object ) + { + resizeDelta( 1 ); + BucketIndex index = hasher_( object ) % buckets_.size(); + return addObjectToBucket( index, object ); + } + + /// Search for a duplicate of the specified object + /// @return address of the duplicate if found, 0 otherwise. + Object *contains( const LookUpKey &key ) const + { + CPPTL_GROWHASTABLE_STATISTICS_UPDATE( ++containsQueryCount_ ); + + BucketIndex index = hasher_( key ) % buckets_.size(); + for ( ChainedObject *current = buckets_[index]; current; current = current->next_ ) + { + CPPTL_GROWHASTABLE_STATISTICS_UPDATE( ++probeCount_ ); + if ( equal_( key, current->object_ ) ) + return ¤t->object_; + } + return 0; + } + + void swap( GrowHashSet &other ) + { + buckets_.swap( other.buckets_ ); + allocator_.swap( other.allocator_ ); + CppTL::swap( size_, other.size_ ); + CppTL::swap( resizeThreshold_, other.resizeThreshold_ ); + #ifdef CPPTL_GROWHASTABLE_STATISTICS + CppTL::swap( collisionCount_, other.collisionCount_ ); + CppTL::swap( probeCount_, other.probeCount_ ); + CppTL::swap( containsQueryCount_, other.containsQueryCount_ ); + #endif + CppTL::swap( hasher_, other.hasher_ ); + CppTL::swap( equal_, other.equal_ ); + } + +private: + typedef typename GrowHashSetTraits<Object>::AllocatedType ChainedObject; + typedef std::vector<ChainedObject *> Buckets; + + struct ThinHashSetEnumByValue + { + typedef Object result_type; + Object operator()( const Object &object ) const + { + return object; + } + }; + + class ThinHashSetEnum + { + public: + typedef Object &value_type; + + ThinHashSetEnum( const Buckets &buckets ) + : currentBucket_( buckets.begin() ) + , endBucket_( buckets.end() ) + , currentObject_( 0 ) + { + findNextBucket(); + } + + bool is_open() const + { + return currentObject_ != 0; + } + + Object ¤t() const + { + CPPTL_ENUMERATOR_CHECK_CURRENT; + return currentObject_->object_; + } + + void advance() + { + CPPTL_ENUMERATOR_CHECK_ADVANCE; + currentObject_ = currentObject_->next_; + if ( !currentObject_ ) + findNextBucket(); + } + + void findNextBucket() + { + while ( currentBucket_ != endBucket_ && *currentBucket_ == 0 ) + ++currentBucket_; + if ( currentBucket_ != endBucket_ ) + currentObject_ = *currentBucket_++; + } + private: + typename Buckets::const_iterator currentBucket_; + typename Buckets::const_iterator endBucket_; + ChainedObject *currentObject_; + }; + + Object &addObjectToBucket( BucketIndex index, + const Object &object ) + { + ++size_; + ChainedObject *newObject = allocator_.allocate(); + new (newObject) ChainedObject( object, buckets_[index] ); + buckets_[index] = newObject; + return newObject->object_; + } + + void resizeDelta( BucketIndex delta ) + { + if ( size_ + delta <= resizeThreshold_ ) + return; + BucketIndex newSize = BucketIndex( (buckets_.size() + delta) * 1.3 ); + if ( newSize < 32 ) + newSize = 32; + + Buckets oldBuckets( newSize, 0 ); + buckets_.swap( oldBuckets ); + resizeThreshold_ = BucketIndex( newSize * 0.8 ); + + for ( Buckets::const_iterator it = oldBuckets.begin(); + it != oldBuckets.end(); + ++it ) + { + for ( ChainedObject *current = *it; current; ) + { + ChainedObject *toMove = current; + current = current->next_; + BucketIndex index = hasher_( toMove->object_ ) % newSize; + toMove->next_ = buckets_[index]; + buckets_[index] = toMove; + } + } + } + + // Allocator for items in the bucket + Allocator allocator_; + + Buckets buckets_; + BucketIndex size_; + BucketIndex resizeThreshold_; +#ifdef CPPTL_GROWHASTABLE_STATISTICS + StatisticCounter collisionCount_; + StatisticCounter probeCount_; + StatisticCounter containsQueryCount_; +#endif + Hasher hasher_; + EqualPred equal_; +}; + + + + + +/* Growing hash table + * This hash-table implementation offer the following features: + * - once inserted in the hash-table, the address of an object will always + * be the same, regardless of resizing. Object are obviously discarded on assignement. + * - on bucket resize, all objects are rehashed + */ +template<typename Key + ,typename Value + ,typename KeyHasher=DefaultHasher<Key> + ,typename KeyEqualPred=std::equal_to<Key> + ,typename Allocator=BatchAllocator< typename GrowHashMapTraits<Key,Value>::AllocatedType > + > +class GrowHashMap +{ +public: + typedef unsigned int BucketIndex; + typedef Entry<Key,Value> Entry; + + GrowHashMap( BucketIndex initialBuckets = 7 ) + : set_( initialBuckets ) + { + } + + GrowHashMap( Allocator allocator, + BucketIndex initialBuckets = 7 ) + : set_( allocator, initialBuckets ) + { + } + + GrowHashMap( const GrowHashMap &other ) + : set_( other.set_ ) + { + } + + GrowHashMap &operator =( const GrowHashMap &other ) + { + GrowHashMap temp( other ); + swap( temp ); + return *this; + } + + // Set the page size for the bucket entry page allocator. + void setPageSize( unsigned int objectsPerPage ) + { + set_.setPageSize( objectsPerPage ); + } + + BucketIndex size() const + { + return set_.size(); + } + + bool empty() const + { + return set_.empty() + } + + void setKeyHasher( KeyHasher hasher ) + { + set_.setHasher( EntryHasher( hasher ) ); + } + + void setKeyEqualPred( KeyEqualPred equal ) + { + set_.setEqualPred( EntryEqualPred( equal ) ); + } + + void clear() + { + set_.clear(); + } + + /// Safe insertion: search for duplicate and insert only if no duplicate found + Entry &add( const Key &key, const Value &value, bool *isDuplicate = 0 ) + { + Entry entry( key, value ); + return set_.add( entry, isDuplicate ); + } + + /// Safe insertion: add or replace the existing entry. + Entry &replace( const Key &key, const Value &value, bool *isDuplicate = 0 ) + { + Entry entry( key, value ); + return set_.replace( entry ); + } + + /// Fast insertion, but insert the object even if it is a duplicate. + Entry &uncheckedAdd( const Key &key, const Value &value ) + { + Entry entry( key, value ); + return set_.uncheckedAdd( entry ); + } + + Value *contains( const Key &key ) const + { + Entry entry( key ); + Entry *found = set_.contains( entry ); + return found ? &found->value_ : 0; + } + + Entry *containsEntry( const Key &key ) const + { + Entry entry( key ); + return set_.contains( entry ); + } + + Value findWithDefault( const Key &key, + const Value &defaultValue ) const + { + Entry entry( key ); + Entry *found = set_.contains( entry ); + return found ? found->value_ : defaultValue; + } + + void swap( GrowHashMap &other ) + { + set_.swap( other.set_ ); + CppTL::swap( hasher_, other.hasher_ ); + CppTL::swap( equal_, other.equal_ ); + } + +private: + struct EntryHasher + { + EntryHasher( KeyHasher hasher = KeyHasher() ) + : hasher_( hasher ) { + } + + typename KeyHasher::HashKey operator()( const Entry &entry ) const { + return hasher_( entry.key_ ); + } + + KeyHasher hasher_; + }; + + struct EntryEqualPred + { + EntryEqualPred( KeyEqualPred equal = KeyEqualPred() ) + : equal_( equal ) { + } + + bool operator()( const Entry &entry1, const Entry &entry2 ) const { + return equal_( entry1.key_, entry2.key_ ); + } + + KeyEqualPred equal_; + }; + + GrowHashSet<Entry,EntryHasher,EntryEqualPred,Entry,Allocator> set_; +}; + + + + +// Bi directional hash map +template<typename Key + ,typename Value + ,typename KeyHasher=DefaultHasher<Key> + ,typename ValueHasher=DefaultHasher<Value> + ,typename KeyEqualPred=std::equal_to<Key> + ,typename ValueEqualPred=std::equal_to<Value> + > +class GrowBiHashMap +{ +public: + typedef unsigned int BucketIndex; +# ifdef CPPTL_GROWHASTABLE_STATISTICS +# if CPPTL_NO_INT64 + typedef unsigned int StatisticCounter; +# else + typedef CppTL::uint64_t StatisticCounter; +# endif +# endif + + struct Entry + { + Entry() {} + Entry( const Key &key_, const Value &value = Value() ) + : key_( key ), value_( value ) + { + } + + Key key_; + Value value_; + }; + + GrowBiHashMap( BucketIndex initialBuckets = 7 ) + : size_( 0 ) + , resizeThreshold_( 0 ) +#ifdef CPPTL_GROWHASTABLE_STATISTICS + , collisionCount_( 0 ) + , probeCount_( 0 ) + , containsQueryCount_( 0 ) +#endif + { + if ( initialBuckets ) + resizeDelta( initialBuckets ); + } + + GrowBiHashMap( const GrowBiHashMap &other ) + : size_( 0 ) + , resizeThreshold_( 0 ) +#ifdef CPPTL_GROWHASTABLE_STATISTICS + , collisionCount_( 0 ) + , probeCount_( 0 ) + , containsQueryCount_( 0 ) +#endif + { + resizeDelta( other.size_ ); + BucketIndex newSize = buckets_.size(); + for ( Buckets::const_iterator it = other.buckets_[0].begin(); + it != other.buckets_[0].end(); + ++it ) + { + for ( ChainedObject *current = *it; current; current = current->next_ ) + { + BucketIndex keyIndex = keyHasher_( current->entry_.key_ ) % newSize; + BucketIndex valueIndex = valueHasher_( current->entry_.value_ ) % newSize; + return addObjectToBucket( keyIndex, valueIndex, current->entry_ ); + } + } + } + + ~GrowBiHashMap() + { + } + + GrowBiHashMap &operator =( const GrowBiHashMap &other ) + { + GrowBiHashMap temp( other ); + swap( temp ); + return *this; + } + + // Set the page size for the bucket entry page allocator. + void setPageSize( unsigned int objectsPerPage ) + { + allocator_.setPageSize( objectsPerPage ); + } + + BucketIndex size() const + { + return size_; + } + + bool empty() const + { + return size_ == 0; + } + + void setKeyHasher( KeyHasher hasher ) + { + keyHasher_ = hasher; + } + + void setKeyEqualPred( KeyEqualPred equal ) + { + keyEqual_ = equal; + } + + void setValueHasher( ValueHasher hasher ) + { + valueHasher_ = hasher; + } + + void setValueEqualPred( ValueEqualPred equal ) + { + valueEqual_ = equal; + } + + void clear() + { + allocator_.destructAllocatedObjects(); + if ( !buckets_[0].empty() ) + { + memset( &buckets_[0][0], 0, buckets_[0].size() ); + memset( &buckets_[1][0], 0, buckets_[1].size() ); + } + } + + /// Safe insertion: search for duplicate and insert only if no duplicate found + Entry &add( const Key &key, const Value &value, bool *isDuplicate = 0 ) + { + Entry entry( key, value ); + return addEntry( entry, isDuplicate ); + } + + Entry &add( const Entry &entry, bool *isDuplicate = 0) + { + resizeDelta( 1 ); + BucketIndex index = keyHasher_( entry.key_ ) % buckets_[0].size(); + for ( ChainedObject *current = buckets_[0][index]; current; current = current->next_ ) + { + CPPTL_GROWHASTABLE_STATISTICS_UPDATE( ++collisionCount_ ); + if ( keyEqual_( entry.key_, current->entry_.key_ ) ) + { + if ( isDuplicate ) + *isDuplicate = true; + return current->entry_; + } + } + assert( containsValue( entry.value_ ) == 0 ); // couple key/value must be unique + if ( isDuplicate ) + *isDuplicate = false; + BucketIndex indexValue = valueHasher_( entry.value_ ) % buckets_[0].size(); + return addObjectToBucket( index, indexValue, entry ); + } + + /// Safe insertion: add or replace the existing entry. + Entry &replace( const Key &key, const Value &value, bool *isDuplicate = 0 ) + { + Entry entry( key, value ); + return replace( entry ); + } + + Entry &replace( const Entry &entry, bool *isDuplicate = 0 ) + { + bool duplicate; + Entry *addedEntry = &add( entry, &duplicate ); + if ( duplicate ) + *addedEntry = entry; + if ( isDuplicate ) + *isDuplicate = duplicate; + return addedEntry; + } + + /// Fast insertion, but insert the object even if it is a duplicate. + /// => the object is inserted at the head of the bucket linked list + /// @return reference on the inserted object. This address will never change. + Entry &uncheckedAdd( const Key &key, const Value &value ) + { + Entry entry( key, value ); + return uncheckedAdd( entry ); + } + + Entry &uncheckedAdd( const Entry &entry ) + { + resizeDelta( 1 ); + BucketIndex keyIndex = keyHasher_( entry.key_ ) % buckets_[0].size(); + BucketIndex valueIndex = valueHasher_( entry.value_ ) % buckets_[1].size(); + return addObjectToBucket( keyIndex, valueIndex, entry ); + } + + /// Search for a duplicate of the specified object + /// @return address of the duplicate if found, 0 otherwise. + Entry *contains( const Entry &entry ) const + { + return containsKey( entry.key_ ) || containsValue( entry.value_ ); + } + + /// Search for a duplicate of the specified object + /// @return address of the duplicate if found, 0 otherwise. + Entry *containsKey( const Key &key ) const + { + CPPTL_GROWHASTABLE_STATISTICS_UPDATE( ++containsQueryCount_ ); + + BucketIndex index = keyHasher_( key ) % buckets_[0].size(); + for ( ChainedObject *current = buckets_[0][index]; current; current = current->next_ ) + { + CPPTL_GROWHASTABLE_STATISTICS_UPDATE( ++probeCount_ ); + if ( keyEqual_( key, current->entry_.key_ ) ) + return ¤t->entry_; + } + return 0; + } + + /// Search for a duplicate of the specified object + /// @return address of the duplicate if found, 0 otherwise. + Entry *containsValue( const Value &value ) const + { + CPPTL_GROWHASTABLE_STATISTICS_UPDATE( ++containsQueryCount_ ); + + BucketIndex index = valueHasher_( value ) % buckets_[1].size(); + for ( ChainedObject *current = buckets_[1][index]; current; current = current->next_ ) + { + CPPTL_GROWHASTABLE_STATISTICS_UPDATE( ++probeCount_ ); + if ( valueEqual_( value, current->entry_.value_ ) ) + return ¤t->entry_; + } + return 0; + } + + Key &getKey( const Value &value ) const + { + Entry *entry = containsValue( value ); + assert( entry != 0 ); + return entry->key_; + } + + Value &getValue( const Key &key ) const + { + Entry *entry = containsKey( key ); + assert( entry != 0 ); + return entry->value_; + } + + void swap( GrowBiHashMap &other ) + { + buckets_.swap( other.buckets_[0] ); + buckets_.swap( other.buckets_[1] ); + allocator_.swap( other.allocator_ ); + CppTL::swap( size_, other.size_ ); + CppTL::swap( resizeThreshold_, other.resizeThreshold_ ); + #ifdef CPPTL_GROWHASTABLE_STATISTICS + CppTL::swap( collisionCount_, other.collisionCount_ ); + CppTL::swap( probeCount_, other.probeCount_ ); + CppTL::swap( containsQueryCount_, other.containsQueryCount_ ); + #endif + CppTL::swap( keyHasher_, other.keyHasher_ ); + CppTL::swap( keyEqual_, other.keyEqual_ ); + CppTL::swap( valueHasher_, other.valueHasher_ ); + CppTL::swap( valueEqual_, other.valueEqual_ ); + } + +private: + struct ChainedObject + { + ChainedObject( const Entry &entry, ChainedObject *nextKey, ChainedObject *nextValue ) + : entry_( entry ) + { + next_[0] = nextKey; + next_[1] = nextValue; + } + Entry entry_; + ChainedObject *next_[2]; + }; + + Entry &addObjectToBucket( BucketIndex keyIndex, + BucketIndex valueIndex, + const Entry &entry ) + { + ++size_; + ChainedObject *newObject = allocator_.allocate(); + new (newObject) ChainedObject( entry, buckets_[0][keyIndex], buckets_[1][valueIndex] ); + buckets_[0][keyIndex] = newObject; + buckets_[1][valueIndex] = newObject; + return newObject->entry_; + } + + void resizeDelta( BucketIndex delta ) + { + if ( size_ + delta <= resizeThreshold_ ) + return; + BucketIndex newSize = (buckets_.size() + delta) * 1.3; + if ( newSize < 32 ) + newSize = 32; + + Buckets oldKeyBuckets( newSize, 0 ); + Buckets oldValueBuckets( newSize, 0 ); + buckets_[0].swap( oldKeyBuckets ); + buckets_[1].swap( oldValueBuckets ); + resizeThreshold_ = newSize * 0.8; + + for ( Buckets::const_iterator it = oldKeyBuckets.begin(); + it != oldKeyBuckets.end(); + ++it ) + { + for ( ChainedObject *current = *it; current; ) + { + ChainedObject *toMove = current; + current = current->next_; + BucketIndex keyIndex = keyHasher_( toMove->entry_.key_ ) % newSize; + toMove->next_[0] = buckets_[0][keyIndex]; + buckets_[0][keyIndex] = toMove; + BucketIndex valueIndex = valueHasher_( toMove->entry_.value_ ) % newSize; + toMove->next_[1] = buckets_[1][valueIndex]; + buckets_[1][valueIndex] = toMove; + } + } + } + + // Allocator for items in the bucket + BatchAllocator<ChainedObject> allocator_; + + typedef std::vector<ChainedObject *> Buckets; + Buckets buckets_[2]; + BucketIndex size_; + BucketIndex resizeThreshold_; +#ifdef CPPTL_GROWHASTABLE_STATISTICS + StatisticCounter collisionCount_; + StatisticCounter probeCount_; + StatisticCounter containsQueryCount_; +#endif + KeyHasher keyHasher_; + KeyEqualPred keyEqual_; + ValueHasher valueHasher_; + ValueEqualPred valueEqual_; +}; + + +} // namespace CppTL { + + +#endif // CPPTL_GROWHASHTABLE_H_INCLUDED Added: rfta/trunk/include/cpptl/intrusiveslist.h =================================================================== --- rfta/trunk/include/cpptl/intrusiveslist.h (rev 0) +++ rfta/trunk/include/cpptl/intrusiveslist.h 2007-04-14 22:49:12 UTC (rev 13) @@ -0,0 +1,144 @@ +#ifndef CPPTL_INTRUSIVESLIST_H_INCLUDED +# define CPPTL_INTRUSIVESLIST_H_INCLUDED + +# include "enumerator.h" + +namespace CppTL { + +/** A single linked list using a BatchAllocator for node. + * @warning default copy constructor share the linked list content between the copy + * @warning Does not assume owernship of elements. + */ +template<typename Object + ,const size_type nextOffset> +class IntrusiveSList +{ +public: + template<typename Object, typename NodeType> class SListThinEnum; + typedef SugarEnumerator< SListThinEnum<Object,Object> > Enum; + typedef SugarEnumerator< SListThinEnum<const Object,Object> > ConstEnum; + + IntrusiveSList() + : head_( 0 ) + { + } + + ~IntrusiveSList() + { +#ifndef NDEBUG + clear(); +#endif + } + + bool empty() const + { + return head_ == 0; + } + + void clear() + { +#ifndef NDEBUG + Object *current = head_; + while ( current ) + { + Object *objectToClean = current; + current = chainedNext( *current ); + chainedNext( *objectToClean ) =0; + } +#endif + head_ = 0; + } + + Enum enumItems() + { + return CppTL::Enum::sugar( SListThinEnum<Object,Object>( head_ ) ); + } + + ConstEnum enumItems() const + { + return CppTL::Enum::sugar( SListThinEnum<const Object,Object>( head_ ) ); + } + + void push_front( const Object &object ) + { + Object *&prevObject = chainedNext(object); + // Notes: this assertion is only true in debug mode + // For optimization, pointer are not reseted when element are removed from list. + CPPTL_ASSERT_MESSAGE( prevObject == 0, "Attempting to insert an object already in a list." ); + prevObject = head_; + head_ = prevObject; + } + + void pop_front() + { + CPPTL_ASSERT_MESSAGE( head_ != 0, "Can not pop front element of an empty list." ); +#ifndef NDEBUG + Object *objectToClean = head_; + head_ = chainedNext(head_); + chainedNext( objectToClean ) =0; +#else + head_ = chainedNext(head_); +#endif + } + + Object &front() + { + CPPTL_ASSERT_MESSAGE( head_ != 0, "Can not access front element of an empty list." ); + return *head_; + } + + const Object &front() const + { + CPPTL_ASSERT_MESSAGE( head_ != 0, "Can not access front element of an empty list." ); + return *head_; + } + +private: + static inline Object *&chainedNext( const Object &object ) + { + Object *theObject = (Object *)&object; + uint8_t *pObject = (uint8_t *)( theObject ); + return *reinterpret_cast<Object **>( pObject + nextOffset ); + } + + template<typename Value,typename Object> + class SListThinEnum + { + public: + typedef Value &value_type; + + SListThinEnum( Object *head ) + : current_( head ) + { + } + + bool is_open() const + { + return current_ != 0; + } + + Value ¤t() const + { + CPPTL_ENUMERATOR_CHECK_CURRENT; + return *current_; + } + + void advance() + { + CPPTL_ENUMERATOR_CHECK_ADVANCE; + current_ = chainedNext(current_); + } + + private: + Object *current_; + }; + + template<typename Object,typename ObjectType> friend class SListThinEnum; + + Object *head_; +}; + +} // namespace CppTL { + +#endif // CPPTL_INTRUSIVESLIST_H_INCLUDED + Added: rfta/trunk/include/cpptl/slist.h =================================================================== --- rfta/trunk/include/cpptl/slist.h (rev 0) +++ rfta/trunk/include/cpptl/slist.h 2007-04-14 22:49:12 UTC (rev 13) @@ -0,0 +1,134 @@ +#ifndef CPPTL_SLIST_H_INCLUDED +# define CPPTL_SLIST_H_INCLUDED + +# include "batchallocator.h" +# include "enumerator.h" + +namespace CppTL { + +/** A single linked list using a BatchAllocator for node. + * @warning default copy constructor share the linked list content between the copy + */ +template<typename Object> +class SList +{ +private: + struct Node + { + typedef Object Type; + Node( const Object &object, Node *next ) + : object_( object ) + , next_( next ) + { + } + + Object object_; + Node *next_; + }; + +public: + typedef BatchAllocator<Node> Allocator; + template<typename Object, typename NodeType> class SListThinEnum; + typedef SugarEnumerator< SListThinEnum<Object,Node> > Enum; + typedef SugarEnumerator< SListThinEnum<const Object,const Node> > ConstEnum; + + SList() + : head_( 0 ) + { + } + + bool empty() const + { + return head_ == 0; + } + + void clear( Allocator &allocator ) + { + Node *current = head_; + while ( current ) + { + Node *toDelete = current; + current = current->next_; + allocator.destruct( toDelete ); + } + head_ = 0; + } + + Enum enumItems() + { + return CppTL::Enum::sugar( SListThinEnum<Object,Node>( head_ ) ); + } + + ConstEnum enumItems() const + { + return CppTL::Enum::sugar( SListThinEnum<const Object,const Node>( head_ ) ); + } + + void push_front( const Object &object, + Allocator &allocator ) + { + head_ = new (allocator.allocate()) Node( object, head_ ); + } + + void pop_front( Allocator &allocator ) + { + Node *oldHead = head_; + head_ = head_->next_; + allocator.destruct( oldHead ); + } + + Object &front() + { + assert( head_ != 0 ); + return head_->object_; + } + + const Object &front() const + { + assert( head_ != 0 ); + return head_->object_; + } + +private: + template<typename Object + ,typename NodeType> + class SListThinEnum + { + public: + typedef Object &value_type; + + SListThinEnum( NodeType *head ) + : current_( head ) + { + } + + bool is_open() const + { + return current_ != 0; + } + + Object ¤t() const + { + CPPTL_ENUMERATOR_CHECK_CURRENT; + return current_->object_; + } + + void advance() + { + CPPTL_ENUMERATOR_CHECK_ADVANCE; + current_ = current_->next_; + } + + private: + NodeType *current_; + }; + + template<typename Object, typename NodeType> friend class SListThinEnum; + + Node *head_; +}; + +} // namespace CppTL { + +#endif // CPPTL_SLIST_H_INCLUDED + Added: rfta/trunk/include/cpptl/stack.h =================================================================== --- rfta/trunk/include/cpptl/stack.h (rev 0) +++ rfta/trunk/include/cpptl/stack.h 2007-04-14 22:49:12 UTC (rev 13) @@ -0,0 +1,142 @@ +#ifndef CPPTL_STACK_H_INCLUDED +# define CPPTL_STACK_H_INCLUDED + +# include "config.h" + +namespace CppTL { + +template<class ElementType > +class Stack +{ +public: + typedef ElementType value_type; + + Stack( size_type pageSize = CPPTL_MAX(32,(1024-32)/sizeof(ElementType)) ) + : pageSize_( pageSize ) + { + initialize(); + } + + ~Stack() + { + while ( !empty() ) // Could be optimized + pop(); + ElementType *page = freePages_; + while ( page ) + { + ElementType *pageToRelease = page; + page = chainedPage( page ); + releasePage( pageToRelease ); + } + } + + bool empty() const + { + return last_ == 0; + } + + inline void push( const ElementType &element ) + { + ElementType *address = unitializedPush(); + new (address) ElementType( element ); + } + + /// Avoid cost of copy construction. Caller is responsible + // for calling placement new. + inline ElementType *unitializedPush() + { + if ( last_ == currentPageEnd_ ) + return unitializedPushNewPage(); + else + return ++last_; + } + + inline ElementType &top() + { + CPPTL_ASSERT_MESSAGE( !empty(), "Stack is empty, can not access top element." ); + return *last_; + } + + inline const ElementType &top() const + { + CPPTL_ASSERT_MESSAGE( !empty(), "Stack is empty, can not access top element." ); + return *last_; + } + + inline void pop() + { + CPPTL_ASSERT_MESSAGE( !empty(), "Stack is empty, can not pop element." ); + last_->~ElementType(); + if ( last_ != currentPage_ ) + --last_; + else + popPreviousPage(); + } + +private: + void initialize() + { + freePages_ = 0; + currentPage_ = 0; + currentPageEnd_ = 0; + last_ = 0; + } + + ElementType *unitializedPushNewPage() + { + ElementType *newPage = allocatePage(); + chainedPage( newPage ) = currentPage_; + currentPage_ = newPage; + currentPageEnd_ = currentPage_ + pageSize_; + last_ = currentPage_; + return last_; + } + + void popPreviousPage() + { + ElementType *prevPage = chainedPage( currentPage_ ); + chainedPage( currentPage_ ) = freePages_; + freePages_ = currentPage_; + currentPage_ = prevPage; + if ( prevPage != 0 ) + { + currentPageEnd_ = prevPage + pageSize_; + last_ = currentPageEnd_ - 1; + } + else + { + currentPageEnd_ = 0; + last_ = 0; + } + } + + ElementType *allocatePage() + { + return (ElementType *)malloc( sizeof(ElementType) * pageSize_ + sizeof(ElementType *) ); + } + + void releasePage( ElementType *page ) + { + free( page ); + } + + ElementType *&chainedPage( ElementType *page ) + { + return *reinterpret_cast<ElementType **>( &page[pageSize_] ); + } + +private: + ElementType *freePages_; + ElementType *currentPage_; + ElementType *currentPageEnd_; + ElementType *last_; + size_type pageSize_; +}; + + + +} // namespace CppTL { + + + +#endif // CPPTL_STACK_H_INCLUDED Modified: rfta/trunk/include/rfta/cpptokensid.h =================================================================== --- rfta/trunk/include/rfta/cpptokensid.h 2007-04-13 07:56:03 UTC (rev 12) +++ rfta/trunk/include/rfta/cpptokensid.h 2007-04-14 22:49:12 UTC (rev 13) @@ -20,7 +20,10 @@ #define IS_EXTCATEGORY(tok, cat) \ ((EXTCATEGORY_FROM_TOKEN(tok) == (cat)) ? true : false) \ /**/ +/// Get id of the token after removal of alt and trigraph specifics. +#define RFTA_STANDARD_ID_FROM_TOKEN( token ) TokenId((token) & MainTokenMask) + /////////////////////////////////////////////////////////////////////////////// // the TokenCategory helps to classify the different token types enum TokenCategory { Modified: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h 2007-04-13 07:56:03 UTC (rev 12) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-14 22:49:12 UTC (rev 13) @@ -2,16 +2,27 @@ # define RFTA_CXXPARSERACTION_H_INCLUDED # include "cxxparser.h" +# include "cxxtype.h" +# include <cpptl/stack.h> namespace Rfta { + class CxxParserAction : public CxxParserDelegate { +public: + CxxParserAction( DeclarationManager &declManager ); + public: // overridden from CxxParserDelegate virtual void declareAndEnterNamespace(const TokenScannerPosRange &id); virtual void exitNamespaceDeclaration(); virtual void handleDeclarationError(const TokenScannerPosRange &error_tokens); virtual void handleStatementError(const TokenScannerPosRange &error_tokens); + +private: + DeclarationManager &decls_; + CppTL::Stack<NamespaceScope *> namespaceScopes_; + //ScopeManager scopeManager_; }; } // namespace Rfta { Added: rfta/trunk/include/rfta/cxxtype.h =================================================================== --- rfta/trunk/include/rfta/cxxtype.h (rev 0) +++ rfta/trunk/include/rfta/cxxtype.h 2007-04-14 22:49:12 UTC (rev 13) @@ -0,0 +1,120 @@ +#ifndef RFTA_CXXTYPE_H_INCLUDED +# define RFTA_CXXTYPE_H_INCLUDED + +# include "cxxparserbase.h" +# include <cpptl/batchallocator.h> +# include <cpptl/growhashtable.h> +# include <cpptl/slist.h> +# include <cpptl/intrusiveslist.h> +# include <cpptl/conststring.h> +# include <deque> +# include <stack> + +namespace Rfta { + +// namespace Impl { +// struct PhantomDeclarationId +// { +// }; +// struct PhantomScopeId : public PhantomDeclarationId +// { +// }; +// struct PhantomNamespaceId : public PhantomScopeId +// { +// }; +// struct PhantomClassId : public PhantomScopeId +// { +// }; +// struct PhantomEnumId : public PhantomDeclarationId +// { +// }; +// +// } // namespace Impl { +// +//typedef Impl::PhantomScopeId *ScopeId; +//typedef Impl::PhantomNamespaceId *NamespaceId; +//typedef Impl::PhantomEnumId *EnumId; + +class Scope +{ +public: + Scope(); + virtual ~Scope(); + +private: + Scope( const Scope &other ); + Scope &operator =( const Scope &other ); + +public: // implementation detail + Scope *nextScopeInParent_; +}; + +typedef CppTL::IntrusiveSList<Scope,offsetof(Scope,nextScopeInParent_)> ChildScopes; + + +class Declaration +{ +public: + Declaration(); + virtual ~Declaration(); + +private: + Declaration( const Declaration &other ); + Declaration &operator =( const Declaration &other ); +}; + + +class NamespaceScope : public Scope +{ +public: + void addNamespace( NamespaceScope &scope ); + +private: +// typedef CppTL::GrowHashMap<TextId, Declaration *> DeclarationsByName; +// DeclarationsByName declarationsByName_; + ChildScopes scopes_; +}; + + +class GlobalNamespaceScope : public NamespaceScope +{ +public: +}; + + +class AnonymousNamespaceScope : public NamespaceScope +{ +public: +}; + + +class NamespaceDecl : public Declaration + , public NamespaceScope +{ +public: + NamespaceDecl( const LocatedSymbol &id, + NamespaceScope &parentScope ); + +private: + LocatedSymbol id_; + NamespaceScope &parentScope_; +}; + + +class DeclarationManager +{ +public: + GlobalNamespaceScope &getGlobalNamespaceScope(); + + NamespaceScope &declareNamespace( const LocatedSymbol &id, NamespaceScope &scope ); + //ScopeId declareAnynonmousNamespace( const Location &location, ScopeId scope ); + //EnumId declareEnum( const LocatedSymbol &id, ScopeId scope ); +private: + GlobalNamespaceScope globalNamespace_; + CppTL::BatchAllocator<NamespaceDecl> namespaceDeclAlloc_; +}; + + +} // namespace CppAnalysis { namespace Parser { + +#endif // RFTA_CXXTYPE_H_INCLUDED Added: rfta/trunk/include/rfta/cxxtype_old.h =================================================================== --- rfta/trunk/include/rfta/cxxtype_old.h (rev 0) +++ rfta/trunk/include/rfta/cxxtype_old.h 2007-04-14 22:49:12 UTC (rev 13) @@ -0,0 +1,799 @@ +#ifndef RFTA_CXXTYPE_H_INCLUDED +# define RFTA_CXXTYPE_H_INCLUDED + +# include "cxxparserbase.h" +# include <cpptl/batchallocator.h> +# include <cpptl/growhashtable.h> +# include <cpptl/slist.h> +# include <cpptl/conststring.h> +# include <deque> +# include <stack> + +namespace Rfta { + +class CxxType; +class Declaration; +class TemplateArgument; +class TemplateArguments; + +typedef const CxxType *TypeId; +typedef unsigned int TypeIdListId; +typedef const TemplateArgument *TemplateArgumentId; +typedef const TemplateArguments *TemplateArgumentsId; + + +enum BuiltInType +{ + bitVoid = 0, + bitChar, + bitWChar, + bitInt, + bitShortInt, + bitLongInt, + bitLongLong, + bitFloat, + bitDouble, + bitLongDouble, + bitBool, + bitMsExtInt8, + bitMsExtInt16, + bitMsExtInt32, + bitMsExtInt64, + bitMaxCount, + bitBitSize = 5 +}; + +enum BuiltInSign +{ + bisUnspecified = 0, + bisSigned, + bisUnsigned, + bisBitSize = 2 +}; + +enum FunctionSpecifier +{ + fsNone = 0, + fsInline = 0x1, + fsVirtual = 0x2, + fsExplicit = 0x4, + fsMsExtCDeclCall = 0x8, + fsMsExtFastCall = 0x10, + fsMsExtStdCall = 0x20, + fsMsExtThisCall = 0x40 +}; + +enum StorageSpecifier +{ + ssNone = 0, + ssStatic = 0x1, + ssAuto = 0x2, + ssRegister = 0x4, + ssExtern = 0x8, + ssMutable = 0x10, + ssDLLImport = 0x20, // _cdecl( dllimport ) + ssDLLExport = 0x40, // _cdecl( dllexport ) + ssThreadStorage = 0x80 // // _cdecl( thread ) +}; + + +enum AccessSpecifier +{ + asNone = 0, + asPublic, + asPrivate, + asProtected +}; + +enum ConstVolatileSpecifier +{ + cvsNone = 0, + cvsConst = 1, + cvsVolatile = 2, + cvsBitSize = 2 +}; + + +enum ClassKeyType +{ + cktStruct = 1, + cktClass, + cktUnion, + cktMaxCount, + cktBitSize = 2, + cktMask = (1<<cktBitSize)-1 +}; + +enum OperatorId +{ + operatorInvalid = 0, + operatorPlus, + operatorMinus, + operatorStar, + operatorDivide, + operatorPercent, + operatorXor, + operatorAnd, + operatorOr, + operatorComplement, + operatorNot, + operatorAssign, + operatorLess, + operatorGreater, + operatorPlusAssign, + operatorMinusAssign, + operatorStarAssign, + operatorDivideAssign, + operatorPercentAssign, + operatorXorAssign, + operatorAndAssign, + operatorOrAssign, + operatorShiftLeft, + operatorShiftRight, + operatorShiftRightAssign, + operatorShiftLeftAssign, + operatorEqual, + operatorNotEqual, + operatorLessOrEqual, + operatorGreaterOrEqual, + operatorLogicalAnd, + operatorLogicalOr, + operatorPlusPlus, // need full function signature to be qualified + operatorMinusMinus, + operatorPreDecrement, + operatorPostDecrement, + operatorPreIncrement, + operatorPostIncrement, + operatorComma, + operatorArrowStar, + operatorArrow, + operatorCall, // () + operatorArray, // [] + operatorNew, + operatorNewArray, + operatorDelete, + operatorDeleteArray, + operatorMaxCount +}; + +CppTL::ConstString builtInTypeAsString( BuiltInSign sign, BuiltInType type ); + +CppTL::ConstString cvSpecifierAsString( unsigned int cvSpecifier ); + +CppTL::ConstString classKeyAsString( ClassKeyType classKey ); + +CppTL::ConstString operatorIdAsString( OperatorId operatorId ); + +class CxxType +{ +public: + enum Kind + { + kindUndefined = 0, + kindBuiltIn, + kindPointer, + kindReference, + kindMemberPointer, + kindArray, + kindFunction, + kindClass, + kindTypedef, + kindEllipsis, + kindTemplateParameter, + kindTemplateId, // instantiated template class + kindMaxCount, + kindMask = 0xf + }; + + typedef unsigned int HashKey; + + CxxType(); + + Kind getKind() const; + + bool isUndefined() const; + + bool isConst() const; + bool isVolatile() const; + + void setIsConst( bool isConst = true ); + void setIsVolatile( bool isVolatile = true ); + // Accept a bit set of ConstVolatileSpecifier + void setCVSpecifier( unsigned int cvSpecifier ); + unsigned int getCVSpecifier() const; + + bool isBuiltInType() const; + void setBuildInType( BuiltInSign sign, BuiltInType type ); + BuiltInType getBuiltInType() const; + BuiltInSign getBuiltInSign() const; + + bool isFunctionType() const; + void setFunctionType( TypeId returnTypeId, + TypeIdListId parameterTypes, + unsigned int cvSpecifier ); + TypeIdListId getFunctionParameterTypes() const; + + void setPointerType( TypeId pointedTypeId, unsigned int cvSpecifier ); + void setReferenceType( TypeId referencedTypeId, unsigned int cvSpecifier ); + void setMemberPointerType( TypeId pointedTypeId, unsigned int cvSpecifier ); + // @todo add array bound + void setArrayType( TypeId pointedTypeId ); + void setTypedefType( TypeId aliasedTypeId ); + + void setClassType( ClassKeyType classKey, + Declaration &classDecl ); + bool isClassType() const; + ClassKeyType getClassKey() const; + Declaration &getClassDecl() const; + + void setTemplateParameterType( Declaration ¶meterDecl ); + Declaration &getTemplateParameterDecl() const; + + void setEllipsisType(); + + void setTemplateIdType( Declaration &templateClassDecl, + TemplateArgumentsId arguments ); + Declaration &getTemplateIdDecl() const; + TemplateArgumentsId getTemplateIdArguments() const; + + + TypeId getSubType() const; + + HashKey hash() const; + + bool operator ==( const CxxType &other ) const; + bool operator !=( const CxxType &other ) const; + +private: + /// Function returns type, array/referenced/pointed type, typedef alias type + TypeId subType_; + Declaration *declarationId_; + union { + TypeIdListId parameterTypes_; + TemplateArgumentsId templateArguments_; + }; + unsigned int cvSpecifier_ : cvsBitSize; + BuiltInType builtInType_ : bitBitSize; + BuiltInSign builtInSign_ : bisBitSize; + Kind kind_ : 4; + ClassKeyType classKey_ : cktBitSize; +}; + + +struct CxxTypeHasher +{ + typedef CxxType::HashKey HashKey; + HashKey operator()( const CxxType &type ) const + { + return type.hash(); + } +}; + + +class CxxTypeManager +{ +public: + TypeId declareType( const CxxType &type ); + + const CxxType &getType( TypeId typeId ) const; + +private: + CppTL::GrowHashSet<CxxType,CxxTypeHasher> types_; +}; + + +typedef std::vector<TypeId> TypeIdList; + +class CxxTypeIdListManager +{ +public: + TypeIdListId declare( const TypeIdList &typeIdList ); + const TypeIdList &getTypeIdList( TypeIdListId id ) const; + +private: + std::deque<TypeIdList> typeIdLists_; +}; + + +class TemplateArgument +{ +public: + typedef unsigned int HashKey; + + enum Kind + { + takType = 1, + takConstant, + takTemplate + }; + + HashKey hash() const; + bool operator ==( const TemplateArgument &other ) const; + bool operator !=( const TemplateArgument &other ) const; + + TypeId type_; + Kind kind_; +}; + +/// A list of template argument (template-id parameters for template instantiation). +class TemplateArguments +{ +public: + typedef unsigned int HashKey; + + TemplateArguments(); + + // Call this once all arguments have been added (compute hash key). + void finalize(); + + HashKey hash() const; + + bool operator ==( const TemplateArguments &other ) const; + bool operator !=( const TemplateArguments &other ) const; + + typedef CppTL::SList<TemplateArgumentId> Arguments; + typedef Arguments::Allocator Allocator; + Arguments arguments_; + HashKey hash_; +}; + + +class TemplateArgumentsManager +{ +public: + TemplateArgumentsId declare( const TemplateArguments &arguments ); + const TemplateArguments &getTemplateArguments( TemplateArgumentsId id ) const; + + TemplateArgumentId declare( const TemplateArgument &argument ); + const TemplateArgument &getTemplateArgument( TemplateArgumentId id ) const; + + TemplateArguments::Allocator &argumentsAllocator(); + +private: + TemplateArguments::Allocator allocator_; + CppTL::GrowHashSet<TemplateArguments + ,CppTL::HashMethodHasher<TemplateArguments> > argumentsLists_; + CppTL::GrowHashSet<TemplateArgument + ,CppTL::HashMethodHasher<TemplateArgument> > uniqueArguments_; +}; + + + +struct BaseClassInfo +{ + TypeId base_; + AccessSpecifier access_; + bool isVirtual_; +}; + +typedef std::vector<BaseClassInfo> BaseClassInfos; + +class Declaration; +typedef std::deque<Declaration *> Declarations; +struct AnonymousScopeInfo; +struct ClassInfo; +struct DeclarationNameHasher; +struct DeclarationNameEqualPred; +struct GlobalScopeInfo; +struct NamespaceInfo; +struct TemplateInfo; + + +typedef CppTL::BatchAllocator< + CppTL::GrowHashSetTraits<Declaration *>::AllocatedType + > DeclarationsByNameAllocator; + +typedef CppTL::ProxyAllocator<DeclarationsByNameAllocator> DeclarationsByNameProxyAllocator; + +// Set of Declaration *, but use TextId for look-up. +// All hash-set use the same allocator. +typedef CppTL::GrowHashSet<Declaration * + ,DeclarationNameHasher + ,DeclarationNameEqualPred + ,TextId + ,DeclarationsByNameProxyAllocator + > DeclarationsByName; + +typedef CppTL::ProxyAllocator<CppTL::BatchAllocator< + CppTL::GrowHashMapTraits<const TemplateArguments * + ,Declaration *>::AllocatedType > + > TemplateInstantiationsAllocator; +// For each template arguments set, associated the instantiated declaration. +typedef CppTL::GrowHashMap<const TemplateArguments * + ,Declaration * + ,CppTL::DefaultHasher<const TemplateArguments *> + ,std::equal_to<const TemplateArguments *> + ,TemplateInstantiationsAllocator + > TemplateInstantiations; + +struct ParameterInfo +{ + TypeId type_; + TextId name_; + bool hasDefault_; +}; + +typedef std::vector<Declaration *> ParameterInfos; + +/// A function declaration (prototype) +struct FunctionInfo +{ + ParameterInfos parameters_; + TextId name_; + TypeId type_; + TypeIdListId exceptions_; + std::vector<Declaration *> locals_; + unsigned int cvSpecifier_ : cvsBitSize; +}; + +/// A class constructor declaration. Parent declaration is the class +struct ConstructorInfo +{ + ParameterInfos parameters_; + bool isExplicit_ : 1; +}; + +/// A class destructor declaration. Parent declaration is the class +struct DestructorInfo +{ + TypeIdListId exceptions_; +}; + +/// A variable (global or class member) declaration +struct VariableInfo +{ + TextId name_; + TypeId type_; +}; + +/// A type alias definition +struct TypedefInfo +{ + TextId name_; + TypeId type_; +}; + +// A template parameter +struct TemplateTypeParameterInfo +{ + TextId name_; + TypeId type_; + Declaration *defaultType_; +}; + +// A template parameter +struct TemplateTemplateParameterInfo +{ + TextId name_; + Declaration *defaultTemplate_; +}; + +// An instantiated template class +struct InstantiatedTemplateClassInfo +{ + const TemplateArguments *arguments_; + Declaration *templateClassDecl_; + TypeId type_; +}; + + +class Declaration +{ +public: + enum DeclarationKind + { + dkGlobalScope = 1, + dkAnonymousNamespace, + dkNamespace, + dkFunction, + dkParameter, + dkClass, + dkVariable, + dkUsingDirective, // using namespace ... + dkUsingDeclaration, + dkTypedef, + dkFriend, + dkConstructor, + dkDestructor, + dkTemplate, // in progress temp... [truncated message content] |
From: <rft...@li...> - 2007-04-13 07:56:05
|
Revision: 12 http://rfta.svn.sourceforge.net/rfta/?rev=12&view=rev Author: blep Date: 2007-04-13 00:56:03 -0700 (Fri, 13 Apr 2007) Log Message: ----------- - added rough parser skeleton using rdpgen. Modified Paths: -------------- rfta/trunk/include/rfta/cpptokens.h rfta/trunk/include/rfta/cpptokensid.h rfta/trunk/include/rfta/lexer.h rfta/trunk/include/rfta/token.h rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj rfta/trunk/makefiles/vs8/rfta.sln rfta/trunk/makefiles/vs8/rfta.suo rfta/trunk/makefiles/vs8/test_rftalexer.vcproj rfta/trunk/test/rftalexer_test.py rfta/trunk/test/testresultbrowser.py rfta/trunk/testdata/.keepme rfta/trunk/tools/rdpgen/codegenerator.py rfta/trunk/tools/rdpgen/howto.txt Added Paths: ----------- rfta/trunk/include/rfta/cxxparseraction.h rfta/trunk/include/rfta/cxxparserbase.h rfta/trunk/include/rfta/forwards.h rfta/trunk/makefiles/vs8/test_rftaparser.vcproj rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user rfta/trunk/src/lib_rftaparser/cxxparser_grammar.config rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp rfta/trunk/src/lib_rftaparser/token.cpp rfta/trunk/src/test_rftaparser/ rfta/trunk/src/test_rftaparser/main.cpp rfta/trunk/testdata/cxxparser_ut/ rfta/trunk/testdata/cxxparser_ut/.keepme rfta/trunk/testdata/cxxparser_ut/t000000_empty.cpp rfta/trunk/testdata/cxxparser_ut/t001000_ns_empty.cpp rfta/trunk/testdata/cxxparser_ut/t001001_ns_nested.cpp rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty.cpp rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty_anonymous.cpp rfta/trunk/testdata/projects/ rfta/trunk/testdata/projects/.keepme Removed Paths: ------------- rfta/trunk/include/rfta/token.cpp rfta/trunk/src/lib_rftaparser/grammar.txt Property Changed: ---------------- rfta/trunk/include/rfta/ rfta/trunk/src/lib_rftaparser/ rfta/trunk/tools/rdpgen/ Property changes on: rfta/trunk/include/rfta ___________________________________________________________________ Name: svn:ignore + cxxparser.h Modified: rfta/trunk/include/rfta/cpptokens.h =================================================================== --- rfta/trunk/include/rfta/cpptokens.h 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/include/rfta/cpptokens.h 2007-04-13 07:56:03 UTC (rev 12) @@ -1,7 +1,7 @@ #ifndef RFTA_CPPTOKENS_H_INCLUDED # define RFTA_CPPTOKENS_H_INCLUDED -# include "config.h" +# include "forwards.h" # include "cpptokensid.h" # include <string> Modified: rfta/trunk/include/rfta/cpptokensid.h =================================================================== --- rfta/trunk/include/rfta/cpptokensid.h 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/include/rfta/cpptokensid.h 2007-04-13 07:56:03 UTC (rev 12) @@ -3,6 +3,8 @@ # include "config.h" +// Notes: T_CONTLINE is duplicate of T_LINECONT + namespace Rfta { /////////////////////////////////////////////////////////////////////////////// Added: rfta/trunk/include/rfta/cxxparseraction.h =================================================================== --- rfta/trunk/include/rfta/cxxparseraction.h (rev 0) +++ rfta/trunk/include/rfta/cxxparseraction.h 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,19 @@ +#ifndef RFTA_CXXPARSERACTION_H_INCLUDED +# define RFTA_CXXPARSERACTION_H_INCLUDED + +# include "cxxparser.h" + +namespace Rfta { + +class CxxParserAction : public CxxParserDelegate +{ +public: // overridden from CxxParserDelegate + virtual void declareAndEnterNamespace(const TokenScannerPosRange &id); + virtual void exitNamespaceDeclaration(); + virtual void handleDeclarationError(const TokenScannerPosRange &error_tokens); + virtual void handleStatementError(const TokenScannerPosRange &error_tokens); +}; + +} // namespace Rfta { + +#endif // RFTA_CXXPARSERACTION_H_INCLUDED Added: rfta/trunk/include/rfta/cxxparserbase.h =================================================================== --- rfta/trunk/include/rfta/cxxparserbase.h (rev 0) +++ rfta/trunk/include/rfta/cxxparserbase.h 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,218 @@ +#ifndef RFTA_PARSER_CXXPARSERBASE_H_INCLUDED +# define RFTA_PARSER_CXXPARSERBASE_H_INCLUDED + +# include <rfta/token.h> +# include <cpptl/conststring.h> +# include <vector> +# include <assert.h> + + +namespace Rfta { + + + +class CxxParserBase +{ +public: + typedef std::vector<Token> Tokens; + typedef Token *TokenScannerPos; + typedef Rfta::TokenId TokenId; + + struct TokenScannerPosRange + { +#ifndef NDEBUG + TokenScannerPosRange() + : start_( 0 ), end_( 0 ) + { + } +#endif + TokenScannerPos start_; + TokenScannerPos end_; + + int length() const + { + assert( start_ != 0 && end_ != 0 ); + return end_ - start_; + } + }; + + typedef std::vector<TokenScannerPosRange> TokenScannerPosRanges; + + CxxParserBase() + : current_( 0 ) + , end_( 0 ) + , traceEnabled_( false ) + , repository_( 0 ) + { + } + + // notes: tokens is garbage after call. + void initialize( Tokens &tokens ) + { + tokens_.swap( tokens ); + current_ = &tokens_.at(0); + end_ = &tokens_.at(0) + tokens_.size(); + } + + void enableTrace( TokenContentManager &repository ) + { + repository_ = &repository; + traceEnabled_ = true; + } + + inline bool match( TokenId id ) + { + assert( current_ != end_ ); + if ( current_->tokenId_ == id ) + { + ++current_; + return true; + } + return false; + } + + inline TokenId getCurrentTokenId() const + { + assert( current_ != end_ ); + return current_->tokenId_; + } + + inline void advance() + { + assert( current_ != end_ ); + ++current_; + } + + inline TokenScannerPos getTokenScannerPos() const + { + return current_; + } + + inline void restoreTokenScannerPos( TokenScannerPos pos ) + { + current_ = pos; + } + + void traceEnterRule( const char *name ) + { + if ( traceEnabled_ ) + { + CppTL::StringBuffer tokensText; + dumpTokens( tokensText ); + printf( "%s=> %s: %s\n", indent_.c_str(), name, tokensText.c_str() ); + indent_ += " "; + } + } + + bool traceExitRule( const char *name, + bool matched ) + { + if ( traceEnabled_ ) + { + indent_ = indent_.substr( 0, indent_.length() - 2 ); + char matchedLetter = matched ? '=' : '#'; + CppTL::StringBuffer tokensText; + dumpTokens( tokensText ); + printf( "%s<%c %s: %s\n", + indent_.c_str(), matchedLetter, name, tokensText.c_str() ); + } + return matched; + } + + void traceSemanticPredicate( const char *name, + const TokenScannerPosRanges ¶meters, + bool matched ) + { + if ( traceEnabled_ ) + traceDelegateCall( matched ? "?=>" : "?#>", name, parameters ); + } + + void traceAction( const char *name, + const TokenScannerPosRanges ¶meters ) + { + if ( traceEnabled_ ) + traceDelegateCall( "! ", name, parameters ); + } + + void traceDelegateCall( const char *prefix, + const char *name, + const TokenScannerPosRanges ¶meters ) + { + if ( !traceEnabled_ ) + return; + + CppTL::StringBuffer buffer; + for ( TokenScannerPosRanges::const_iterator it = parameters.begin(); + it != parameters.end(); + ++it ) + { + if ( it != parameters.begin() ) + buffer += ", "; + buffer += "[[ "; + appendTokenRangeText( buffer, *it ); + buffer += " ]]"; + } + printf( "%s%s %s %s\n", + indent_.c_str(), prefix, name, buffer.c_str() ); + } + + void dumpTokens( CppTL::StringBuffer &tokensText ) const + { + if ( !traceEnabled_ ) + return; + + TokenScannerPosRange range; + range.start_ = current_; + range.end_ = end_; + appendTokenRangeText( tokensText, range, 10 ); + } + + inline void appendTokenText( CppTL::StringBuffer &buffer, + TokenScannerPos token ) const + { + if ( token->tokenId_ == T_IDENTIFIER ) + buffer += "'" + repository_->getTokenText(*token) + "'"; + else + buffer += repository_->getTokenText( *token ); + } + + inline void appendTokenRangeText( CppTL::StringBuffer &buffer, + const TokenScannerPosRange &range, + int maxCount = 1000 ) const + { + for ( TokenScannerPos token = range.start_; + token != range.end_ && maxCount > 0; + ++token, --maxCount ) + { + if ( token != range.start_ ) + buffer += " "; + appendTokenText( buffer, token ); + } + } + +private: + Tokens tokens_; + TokenScannerPos current_; + TokenScannerPos end_; + CppTL::ConstString indent_; + TokenContentManager *repository_; // only available for trace + bool traceEnabled_; +}; + +} // namespace Rfta { + + +// Macros to enable/disable parser rule execution tracing. +# ifndef NDEBUG +# define RFTA_PARSER_TRACE_RULE( method, name ) \ + ( traceEnterRule( name ), traceExitRule( name, method() ) ) +# define RFTA_PARSER_TRACE_DELEGATE actionTracer_ +# define RFTA_PARSER_TRACER ActionTracer +# else +# define RFTA_PARSER_TRACE_RULE( method, name ) method() +# define RFTA_PARSER_TRACE_DELEGATE delegate_ +# define RFTA_PARSER_TRACER CxxParserDelegate +#endif + + +#endif // RFTA_PARSER_CXXPARSERBASE_H_INCLUDED Added: rfta/trunk/include/rfta/forwards.h =================================================================== --- rfta/trunk/include/rfta/forwards.h (rev 0) +++ rfta/trunk/include/rfta/forwards.h 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,19 @@ +#ifndef RFTA_FORWARDS_H_INCLUDED +# define RFTA_FORWARDS_H_INCLUDED + +# include "config.h" + +namespace Rfta { + +typedef unsigned int TextId; +typedef unsigned int FileId; +typedef unsigned int TextPos; + +// token.h +class Token; +class TextRepository; +class TokenStream; + +} // namespace Rfta { + +#endif // RFTA_FORWARDS_H_INCLUDED Modified: rfta/trunk/include/rfta/lexer.h =================================================================== --- rfta/trunk/include/rfta/lexer.h 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/include/rfta/lexer.h 2007-04-13 07:56:03 UTC (rev 12) @@ -1,6 +1,7 @@ #ifndef RFTA_LEXER_H_INCLUDED # define RFTA_LEXER_H_INCLUDED +# include "forwards.h" # include "cpptokensid.h" # include <string> @@ -26,6 +27,26 @@ , enable_ms_extensions_( true ) { } + + TextPos lastTokenPos() const + { + return tokenStart_-begin_; + } + + TextPos lastTokenLength() const + { + return current_-tokenStart_; + } + + const CharType *lastTokenBegin() const + { + return tokenStart_; + } + + const CharType *lastTokenEnd() const + { + return current_; + } TokenRange lastTokenRange() const { Deleted: rfta/trunk/include/rfta/token.cpp =================================================================== --- rfta/trunk/include/rfta/token.cpp 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/include/rfta/token.cpp 2007-04-13 07:56:03 UTC (rev 12) @@ -1,142 +0,0 @@ -#include <rfta/token.h> - -namespace Rfta { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Token -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -Token::Token() - : id_( T_ANY ) - , range_( -1, -1 ) -{ -} - - -Token::Token( TokenId id, - const TextRange &range, - const char *textBegin, - const char *textEnd, - TokenContentFactory &factory ) - : id_( id ) - , range_( range ) -{ - if ( isIdentifier() ) - textId_ = factory.getIdentifierId( textBegin, textEnd ); - else if ( isLiteral() ) - textId_ = factory.getLiteralId( textBegin, textEnd ); - else if ( isWhiteSpace() ) - textId_ = factory.getWhiteSpaceId( textBegin, textEnd ); - else if ( id_ == T_PP_INCLUDE || id_ == T_PP_QHEADER || id_ == T_PP_HHEADER ) - textId_ = factory.getLiteralId( textBegin, textEnd ); - else - textId_ = -1; -} - - -std::string -Token::text( const TokenContentFactory &factory ) const -{ - if ( isIdentifier() ) - return factory.getIdentifierText( textId_ ); - else if ( isLiteral() ) - return factory.getLiteralText( textId_ ); - else if ( isWhiteSpace() ) - return factory.getWhiteSpaceText( textId_ ); - else if ( id() == T_PP_INCLUDE || id() == T_PP_QHEADER || id() == T_PP_HHEADER ) - return factory.getLiteralText( textId_ ); - else - return tokenText( id_ ); -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class TextLigthweightFactory -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -TextId -TextLigthweightFactory::getId( const char *begin, - const char *end ) -{ - return getId( std::string( begin, end ) ); -} - - -TextId -TextLigthweightFactory::getId( const std::string &content ) -{ - IdFromText::iterator it = idFromTexts_.find( content ); - if ( it != idFromTexts_.end() ) - return it->second; - TextId id = idFromTexts_.size() + 1; - idFromTexts_[content] = id; - textFromIds_[id] = content; - return id; -} - - -std::string -TextLigthweightFactory::getText( TextId id ) const -{ - TextFromId::const_iterator it = textFromIds_.find( id ); - if ( it == textFromIds_.end() ) - throw std::invalid_argument( "TokenContentFactory::getText" ); - return it->second; -} - - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class TokenContentFactory -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -IdentifierId -TokenContentFactory::getIdentifierId( const char *begin, - const char *end ) -{ - return identifiers_.getId( begin, end ); -} - -std::string -TokenContentFactory::getIdentifierText( IdentifierId id ) const -{ - return identifiers_.getText( id ); -} - - -LiteralId -TokenContentFactory::getLiteralId( const char *begin, - const char *end ) -{ - return literals_.getId( begin, end ); -} - - -std::string -TokenContentFactory::getLiteralText( LiteralId id ) const -{ - return literals_.getText( id ); -} - - -SpaceId -TokenContentFactory::getWhiteSpaceId( const char *begin, - const char *end ) -{ - return spaces_.getId( begin, end ); -} - -std::string -TokenContentFactory::getWhiteSpaceText( SpaceId id ) const -{ - return spaces_.getText( id ); -} - - -} // namespace Rfta { Modified: rfta/trunk/include/rfta/token.h =================================================================== --- rfta/trunk/include/rfta/token.h 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/include/rfta/token.h 2007-04-13 07:56:03 UTC (rev 12) @@ -2,175 +2,213 @@ # define RFTA_TOKEN_H_INCLUDED # include "cpptokens.h" +# include "lexer.h" +# include <cpptl/conststring.h> # include <map> +# include <assert.h> namespace Rfta { -class TokenContentFactory; + // ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class Token +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// -typedef unsigned int TextOffset; -typedef unsigned int TextId; +class Token +{ +public: + TokenId tokenId_; + TextId text_; + FileId file_; + TextPos pos_; // length is deduced from the text_. +}; -class RFTA_API TextRange +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class TextRepository +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +class TextRepository { public: - TextRange( TextOffset start, - TextOffset end ) - : start_( start ) - , end_( end ) + TextId getLiteralId( const CppTL::ConstString &text ) { + return getId( text, 0 ); } - TextOffset start() const + TextId getIdentifierId( const CppTL::ConstString &text ) { - return start_; + return getId( text, 1 ); } - TextOffset end() const + const CppTL::ConstString &getLiteralText( TextId textId ) const { - return end_; + return getText( textId ); } - TextOffset length() const + const CppTL::ConstString &getIdentifierText( TextId textId ) const { - return end_ - start_; + return getText( textId ); } private: - TextOffset start_; - TextOffset end_; -}; - - -class RFTA_API Token -{ -public: - Token( TokenId id, - const TextRange &range, - const char *textBegin, - const char *textEnd, - TokenContentFactory &factory ); - - Token(); - - TokenId id() const + TextId getId( const CppTL::ConstString &text, TextId orMask ) { - return id_; + Texts2Id::iterator it = texts2id_.find( text ); + if ( it != texts2id_.end() ) + return it->second; + TextId textId = ((texts2id_.size()+1) << 1) | orMask; + texts2id_.insert( Texts2Id::value_type( text, textId ) ); + ids2text_.insert( Ids2Text::value_type( textId, text ) ); + return textId; } - // Returns the T_LEFTBRACE for T_LEFTBRACE, T_LEFTBRACE_ALT & T_LEFTBRACE_TRIGRAPH - TokenId baseId() const + const CppTL::ConstString &getText( TextId textId ) const { - return TokenId( BASEID_FROM_TOKEN( id_ ) ); + assert( ids2text_.count( textId ) > 0 ); + return ids2text_.find( textId )->second; } - TokenCategory category() const - { - return TokenCategory( CATEGORY_FROM_TOKEN( id_ ) ); - } +private: + typedef std::map<TextId,CppTL::ConstString> Ids2Text; // replace with bihash table + typedef std::map<CppTL::ConstString,TextId> Texts2Id; + Ids2Text ids2text_; + Texts2Id texts2id_; +}; - TextRange range() const - { - return range_; - } - TextId textId() const - { - return textId_; - } +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class TokenContentManager +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// - bool isIdentifier() const +class TokenContentManager +{ +public: + enum TextStorageMethod { - return category() == IdentifierTokenType; - } + methodOriginalTokenId = 0, + methodIdentifier, + methodLiteral + }; - bool isLiteral() const + inline static TextStorageMethod getTokenStorageMethod( TokenId tokenId ) { - return (category() & 0xF0000000) == LiteralTokenType; + switch ( tokenId ) + { + // identifiers + case T_IDENTIFIER: + return methodIdentifier; + break; + // literal & special text blocks (macro, asm, comments, spaces) + case T_PP_ERROR: + case T_PP_WARNING: + case T_PP_PRAGMA: + case T_OCTALINT: + case T_DECIMALINT: + case T_HEXAINT: + case T_INTLIT: + case T_FLOATLIT: + case T_CCOMMENT: + case T_CPPCOMMENT: + case T_CHARLIT: + case T_STRINGLIT: + case T_CONTLINE: + case T_SPACE: + case T_SPACE2: + case T_NEWLINE: + case T_UNKNOWN: + case T_PP_INCLUDE: + case T_PP_QHEADER: + case T_PP_HHEADER: + return methodLiteral; + // basic tokens (text can be deduced from token id) + default: + return methodOriginalTokenId; + }; } - bool isWhiteSpace() const + TextId getIdentifierId( const char *begin, const char *end ) { - return category() == WhiteSpaceTokenType; + return repository_.getIdentifierId( CppTL::ConstCharView(begin,end) ); } - bool isWhiteSpaceOrNewLine() const + TextId getLiteralId( const char *begin, const char *end ) { - return isWhiteSpace() || category() == EOLTokenType; + return repository_.getLiteralId( CppTL::ConstCharView(begin,end) ); } - std::string text( const TokenContentFactory &factory ) const; - - bool match( TokenId other ) const + CppTL::ConstString getTokenText( const Token &token ) const { - return baseId() == BASEID_FROM_TOKEN(other); + switch ( getTokenStorageMethod(token.tokenId_) ) + { + default: + CPPTL_DEBUG_ASSERT_UNREACHABLE; + case methodIdentifier: + return repository_.getIdentifierText(token.text_); + case methodLiteral: + return repository_.getLiteralText(token.text_); + case methodOriginalTokenId: + return tokenText( static_cast<TokenId>(token.text_) ); + } } private: - TextRange range_; - TokenId id_; - TextId textId_; + TextRepository repository_; }; +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// class TokenStream +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// -class RFTA_API TextLigthweightFactory +class TokenStream { public: - TextId getId( const char *begin, - const char *end ); + TokenStream( const char *begin, const char *end, + TokenContentManager &contentManager, + FileId fileId ) + : lexer_( begin, end ) + , contentManager_( contentManager ) + , fileId_( fileId ) + { + } - TextId getId( const std::string &content ); - - std::string getText( TextId id ) const; - -private: - typedef std::map<std::string,TextId> IdFromText; - typedef std::map<TextId,std::string> TextFromId; - IdFromText idFromTexts_; - TextFromId textFromIds_; -}; - - -typedef TextId IdentifierId; -typedef TextId LiteralId; -typedef TextId SpaceId; - - - -class RFTA_API TokenContentFactory -{ -public: - IdentifierId getIdentifierId( const char *begin, - const char *end ); - - std::string getIdentifierText( IdentifierId id ) const; - - LiteralId getLiteralId( const char *begin, - const char *end ); - - std::string getLiteralText( LiteralId id ) const; - - SpaceId getWhiteSpaceId( const char *begin, - const char *end ); - - std::string getWhiteSpaceText( SpaceId id ) const; - -private: - TextLigthweightFactory identifiers_; - TextLigthweightFactory literals_; - TextLigthweightFactory spaces_; -}; - - -class RFTA_API TokenSource -{ -public: - virtual ~TokenSource() + void getNextToken( Token &token ) { + TokenId originalTokenId = lexer_.nextToken(); + token.pos_ = lexer_.lastTokenPos(); + token.file_ = fileId_; + switch ( contentManager_.getTokenStorageMethod(originalTokenId) ) + { + case TokenContentManager::methodOriginalTokenId: + token.text_ = originalTokenId; + token.tokenId_ = static_cast<TokenId>( BASEID_FROM_TOKEN(originalTokenId) ); + break; + case TokenContentManager::methodIdentifier: + token.text_ = contentManager_.getIdentifierId( lexer_.lastTokenBegin(), + lexer_.lastTokenEnd() ); + token.tokenId_ = originalTokenId; + break; + case TokenContentManager::methodLiteral: + token.text_ = contentManager_.getLiteralId( lexer_.lastTokenBegin(), + lexer_.lastTokenEnd() ); + token.tokenId_ = originalTokenId; + break; + default: + CPPTL_DEBUG_ASSERT_UNREACHABLE; + }; } - virtual Token nextToken() = 0; +private: + Scanner lexer_; + TokenContentManager &contentManager_; + FileId fileId_; }; Modified: rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj =================================================================== --- rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj 2007-04-13 07:56:03 UTC (rev 12) @@ -16,8 +16,8 @@ <Configurations> <Configuration Name="Debug|Win32" - OutputDirectory="../../build/$(ParentName)_$(ConfigurationName)" - IntermediateDirectory="../../build/$(ParentName)_$(ConfigurationName)" + OutputDirectory="../../build/$(ProjectName)_$(ConfigurationName)" + IntermediateDirectory="../../build/$(ProjectName)_$(ConfigurationName)" ConfigurationType="4" BuildLogFile="" > @@ -44,6 +44,7 @@ StringPooling="true" MinimalRebuild="true" BasicRuntimeChecks="3" + RuntimeLibrary="1" EnableFunctionLevelLinking="true" EnableEnhancedInstructionSet="2" BrowseInformation="1" @@ -82,8 +83,8 @@ </Configuration> <Configuration Name="Release|Win32" - OutputDirectory="../../build/$(ParentName)_$(ConfigurationName)" - IntermediateDirectory="../../build/$(ParentName)_$(ConfigurationName)" + OutputDirectory="../../build/$(ProjectName)_$(ConfigurationName)" + IntermediateDirectory="../../build/$(ProjectName)_$(ConfigurationName)" ConfigurationType="4" BuildLogFile="" > @@ -260,6 +261,38 @@ > </File> </Filter> + <Filter + Name="generated" + > + <File + RelativePath="..\..\src\lib_rftaparser\cxxparser.cpp" + > + </File> + <File + RelativePath="..\..\include\rfta\cxxparser.h" + > + </File> + <File + RelativePath="..\..\src\lib_rftaparser\preprocessorlexer.cpp" + > + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + </Filter> <File RelativePath="..\..\include\rfta\config.h" > @@ -273,10 +306,74 @@ > </File> <File - RelativePath="..\..\src\lib_rftaparser\grammar.txt" + RelativePath="..\..\src\lib_rftaparser\cxxparser_grammar.config" > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCustomBuildTool" + Description="Generating cxxparser" + CommandLine="python ..\..\tools\rdpgen\codegenerator.py $(InputPath)" + AdditionalDependencies="$(InputDir)/cxxparser_grammar.txt" + Outputs="../../include/rfta/cxxparser.h;$(InputDir)/cxxparser.cpp" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCustomBuildTool" + Description="Generating cxxparser" + CommandLine="python ..\..\tools\rdpgen\codegenerator.py $(InputPath)" + AdditionalDependencies="$(InputDir)/cxxparser_grammar.txt" + Outputs="../../include/rfta/cxxparser.h;$(InputDir)/cxxparser.cpp" + /> + </FileConfiguration> </File> <File + RelativePath="..\..\src\lib_rftaparser\cxxparser_grammar.txt" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine="" + AdditionalDependencies="" + Outputs="" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCustomBuildTool" + Description="" + CommandLine="" + AdditionalDependencies="" + Outputs="" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\lib_rftaparser\cxxparseraction.cpp" + > + </File> + <File + RelativePath="..\..\include\rfta\cxxparseraction.h" + > + </File> + <File + RelativePath="..\..\include\rfta\cxxparserbase.h" + > + </File> + <File + RelativePath="..\..\tools\rdpgen\howto.txt" + > + </File> + <File RelativePath="..\..\src\lib_rftaparser\lexer.cpp" > </File> @@ -317,30 +414,10 @@ > </File> <File - RelativePath="..\..\src\lib_rftaparser\preprocessorlexer.cpp" + RelativePath="..\..\src\lib_rftaparser\token.cpp" > - <FileConfiguration - Name="Debug|Win32" - ExcludedFromBuild="true" - > - <Tool - Name="VCCLCompilerTool" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - ExcludedFromBuild="true" - > - <Tool - Name="VCCLCompilerTool" - /> - </FileConfiguration> </File> <File - RelativePath="..\..\include\rfta\token.cpp" - > - </File> - <File RelativePath="..\..\include\rfta\token.h" > </File> Modified: rfta/trunk/makefiles/vs8/rfta.sln =================================================================== --- rfta/trunk/makefiles/vs8/rfta.sln 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/makefiles/vs8/rfta.sln 2007-04-13 07:56:03 UTC (rev 12) @@ -8,6 +8,11 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_rftaparser", "lib_rftaparser.vcproj", "{3554F39E-A332-44F5-A90A-7C76C042959F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_rftaparser", "test_rftaparser.vcproj", "{5EAF4FCB-4E43-4B6B-BA04-5113A93A5CDF}" + ProjectSection(ProjectDependencies) = postProject + {3554F39E-A332-44F5-A90A-7C76C042959F} = {3554F39E-A332-44F5-A90A-7C76C042959F} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -22,6 +27,10 @@ {3554F39E-A332-44F5-A90A-7C76C042959F}.Debug|Win32.Build.0 = Debug|Win32 {3554F39E-A332-44F5-A90A-7C76C042959F}.Release|Win32.ActiveCfg = Release|Win32 {3554F39E-A332-44F5-A90A-7C76C042959F}.Release|Win32.Build.0 = Release|Win32 + {5EAF4FCB-4E43-4B6B-BA04-5113A93A5CDF}.Debug|Win32.ActiveCfg = Debug|Win32 + {5EAF4FCB-4E43-4B6B-BA04-5113A93A5CDF}.Debug|Win32.Build.0 = Debug|Win32 + {5EAF4FCB-4E43-4B6B-BA04-5113A93A5CDF}.Release|Win32.ActiveCfg = Release|Win32 + {5EAF4FCB-4E43-4B6B-BA04-5113A93A5CDF}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Modified: rfta/trunk/makefiles/vs8/rfta.suo =================================================================== (Binary files differ) Modified: rfta/trunk/makefiles/vs8/test_rftalexer.vcproj =================================================================== --- rfta/trunk/makefiles/vs8/test_rftalexer.vcproj 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/makefiles/vs8/test_rftalexer.vcproj 2007-04-13 07:56:03 UTC (rev 12) @@ -16,8 +16,8 @@ <Configurations> <Configuration Name="Debug|Win32" - OutputDirectory="../../build/$(ParentName)_$(ConfigurationName)" - IntermediateDirectory="../../build/$(ParentName)_$(ConfigurationName)" + OutputDirectory="../../build/$(ProjectName)_$(ConfigurationName)" + IntermediateDirectory="../../build/$(ProjectName)_$(ConfigurationName)" ConfigurationType="1" BuildLogFile="" > @@ -94,8 +94,8 @@ </Configuration> <Configuration Name="Release|Win32" - OutputDirectory="../../build/$(ParentName)_$(ConfigurationName)" - IntermediateDirectory="../../build/$(ParentName)_$(ConfigurationName)" + OutputDirectory="../../build/$(ProjectName)_$(ConfigurationName)" + IntermediateDirectory="../../build/$(ProjectName)_$(ConfigurationName)" ConfigurationType="1" BuildLogFile="" > Added: rfta/trunk/makefiles/vs8/test_rftaparser.vcproj =================================================================== --- rfta/trunk/makefiles/vs8/test_rftaparser.vcproj (rev 0) +++ rfta/trunk/makefiles/vs8/test_rftaparser.vcproj 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8,00" + Name="test_rftaparser" + ProjectGUID="{5EAF4FCB-4E43-4B6B-BA04-5113A93A5CDF}" + RootNamespace="test_rftaparser" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="../../build/$(ProjectName)_$(ConfigurationName)" + IntermediateDirectory="../../build/$(ProjectName)_$(ConfigurationName)" + ConfigurationType="1" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="../../include" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" + StringPooling="true" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + EnableFunctionLevelLinking="true" + EnableEnhancedInstructionSet="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="4" + CallingConvention="1" + DisableSpecificWarnings="4996" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + LinkIncremental="2" + GenerateDebugInformation="true" + SubSystem="1" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="../../build/$(ProjectName)_$(ConfigurationName)" + IntermediateDirectory="../../build/$(ProjectName)_$(ConfigurationName)" + ConfigurationType="1" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="../../include" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + StringPooling="true" + RuntimeLibrary="0" + BufferSecurityCheck="false" + EnableFunctionLevelLinking="true" + EnableEnhancedInstructionSet="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="3" + CallingConvention="1" + DisableSpecificWarnings="4996" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + LinkIncremental="1" + GenerateDebugInformation="true" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <File + RelativePath="..\..\src\test_rftaparser\main.cpp" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Added: rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user =================================================================== --- rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user (rev 0) +++ rfta/trunk/makefiles/vs8/test_rftaparser.vcproj.ANABELLE.Zark.user 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioUserFile + ProjectType="Visual C++" + Version="8,00" + ShowAllFiles="false" + > + <Configurations> + <Configuration + Name="Debug|Win32" + > + <DebugSettings + Command="$(TargetPath)" + WorkingDirectory="" + CommandArguments="" + Attach="false" + DebuggerType="3" + Remote="1" + RemoteMachine="ANABELLE" + RemoteCommand="" + HttpUrl="" + PDBPath="" + SQLDebugging="" + Environment="" + EnvironmentMerge="true" + DebuggerFlavor="" + MPIRunCommand="" + MPIRunArguments="" + MPIRunWorkingDirectory="" + ApplicationCommand="" + ApplicationArguments="" + ShimCommand="" + MPIAcceptMode="" + MPIAcceptFilter="" + /> + </Configuration> + <Configuration + Name="Release|Win32" + > + <DebugSettings + Command="$(TargetPath)" + WorkingDirectory="" + CommandArguments="" + Attach="false" + DebuggerType="3" + Remote="1" + RemoteMachine="ANABELLE" + RemoteCommand="" + HttpUrl="" + PDBPath="" + SQLDebugging="" + Environment="" + EnvironmentMerge="true" + DebuggerFlavor="" + MPIRunCommand="" + MPIRunArguments="" + MPIRunWorkingDirectory="" + ApplicationCommand="" + ApplicationArguments="" + ShimCommand="" + MPIAcceptMode="" + MPIAcceptFilter="" + /> + </Configuration> + </Configurations> +</VisualStudioUserFile> Property changes on: rfta/trunk/src/lib_rftaparser ___________________________________________________________________ Name: svn:ignore - lexer.cpp + lexer.cpp cxxparser.cpp Added: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.config =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.config (rev 0) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.config 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,17 @@ +[Grammar] +PARSER_GRAMMAR=cxxparser_grammar.txt + +[CodeGeneration] +PARSER_BASE_CLASS=CxxParserBase +PARSER_CLASS=CxxParser +PARSER_HEADER_PATH=../../include/rfta/cxxparser.h +PARSER_CPP_PATH=cxxparser.cpp +PARSER_HEADER_INCLUDE=<rfta/cxxparser.h> +PARSER_BASE_CLASS_INCLUDE="cxxparserbase.h" +PARSER_DELEGATE_CLASS=CxxParserDelegate +PARSER_NAMESPACE=Rfta +PARSER_CPP_PROLOG= +PARSER_TRACE_RULE_MACRO=RFTA_PARSER_TRACE_RULE +PARSER_TRACE_DELEGATE_MACRO=RFTA_PARSER_TRACE_DELEGATE +PARSER_TRACER_CLASS_MACRO=RFTA_PARSER_TRACER + Added: rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt (rev 0) +++ rfta/trunk/src/lib_rftaparser/cxxparser_grammar.txt 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,53 @@ +::translation_unit + ?(declaration_seq) %T_EOF + +# A.2 + +::identifier + %T_IDENTIFIER + +::statement_error + # look-ahead is not a end of compound statement, then an error occurred + =>( ~'}' ) + $error_tokens=( +( statement_skip_token ) ?';' ) + !handleStatementError[ $error_tokens ] + +::statement_skip_token + statement_skip_error_compound + | ~( %T_EOF | '}' | ';' ) + +::statement_skip_token_in_compound + statement_skip_error_compound + | ~( %T_EOF | '}' ) + +::statement_skip_error_compound + '{' *statement_skip_token_in_compound '}' + +# ############################## A.7: Declaration ############################ + +::declaration_seq + +( =>( ~( %T_EOF | '}' ) ) *declaration ?declaration_error ) + +::declaration + namespace_definition + +::declaration_error + =>( ~( %T_EOF | '}' ) ) # look-ahead is not a end of declaration block, then error + $error_tokens=( +statement_skip_token ?';' ) + !handleDeclarationError[ $error_tokens ] + + +# namespace +# + +::namespace_definition + 'namespace' $id=(?identifier) + '{' + !declareAndEnterNamespace[$id] + @[exitNamespaceDeclaration] + namespace_body + '}' + +::namespace_body + ?declaration_seq + Added: rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp (rev 0) +++ rfta/trunk/src/lib_rftaparser/cxxparseraction.cpp 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,28 @@ +#include <rfta/cxxparseraction.h> + +namespace Rfta { + +void +CxxParserAction::declareAndEnterNamespace(const TokenScannerPosRange &id) +{ +} + + +void +CxxParserAction::exitNamespaceDeclaration() +{ +} + + +void +CxxParserAction::handleDeclarationError(const TokenScannerPosRange &error_tokens) +{ +} + + +void +CxxParserAction::handleStatementError(const TokenScannerPosRange &error_tokens) +{ +} + +} // namespace Rfta { Deleted: rfta/trunk/src/lib_rftaparser/grammar.txt =================================================================== --- rfta/trunk/src/lib_rftaparser/grammar.txt 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/src/lib_rftaparser/grammar.txt 2007-04-13 07:56:03 UTC (rev 12) @@ -1,73 +0,0 @@ -preprocessing_file: - group? - ; - -group: - group_part* - ; - -group_part: - if_section - | control_line - | any* new_line - ; - -if_section: - if_group elif_group* else_group? endif_line - ; - -if_group: - T_PP_IF constant_expression new_line group? - | T_PP_IFDEF - | T_PP_IFNDEF - ; - -elif_group: - T_PP_ELIF constant_expression new_line group? - ; - -else_group: - T_PP_ELSE new_line group? - ; - -endif_line: - T_PP_ENDIF new_line - ; - -control_line: - pp_include - | pp_define - | pp_undef - | pp_line - | pp_error - | pp_pragma - | T_POUND new_line - ; - -pp_include: - ( T_PP_HHEADER - | T_PP_QHEADER - | T_PP_INCLUDE any - ) new_line - ; - -pp_define: - T_PP_DEFINE identifier any* new_line - ; - -pp_undef: - T_PP_UNDEF identifier new_line - ; - -pp_line: - T_PP_LINE any* new_line - ; - -pp_error: - T_PP_ERROR any* new_line - ; - -pp_pragma: - T_PP_PRAGMA any* new_line - ; - Added: rfta/trunk/src/lib_rftaparser/token.cpp =================================================================== --- rfta/trunk/src/lib_rftaparser/token.cpp (rev 0) +++ rfta/trunk/src/lib_rftaparser/token.cpp 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,7 @@ +#include <rfta/token.h> + +namespace Rfta { + + + +} // namespace Rfta { Added: rfta/trunk/src/test_rftaparser/main.cpp =================================================================== --- rfta/trunk/src/test_rftaparser/main.cpp (rev 0) +++ rfta/trunk/src/test_rftaparser/main.cpp 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,158 @@ +#include <rfta/lexer.h> +#include <rfta/cpptokens.h> +#include <rfta/options.inl> +#include <rfta/token.h> +#include <rfta/cxxparser.h> +#include <rfta/cxxparseraction.h> +#include <cpptl/scopedptr.h> +#include <cpptl/stringtools.h> +#include <algorithm> +#include <fstream> +#include <iostream> +#include <stdexcept> +#include <stdio.h> + +/* Test program: + - expect command, then source on stdin + - output synthesis on stdout. + */ + +static bool +readInput( const std::string &file, + std::string &input ) +{ + CppTL::ScopedPtr<std::ifstream> ifs; + if ( !file.empty() ) + { + ifs.reset( new std::ifstream( file.c_str() ) ); + if ( ifs->fail() ) + { + std::cout << "Failed to open input file: '" << file << "'." << std::endl; + return false; + } + } + + std::istream *is = file.empty() ? &std::cin : ifs.get(); + while ( !is->eof() ) + { + int c = is->get(); + if ( c == EOF ) + break; + input += char( c ); + } + return true; +} + + +class OutputFileHandle +{ +public: + OutputFileHandle( const std::string &path, + bool create, + bool appendMode ) + { + failed_ = false; + if ( create ) + { + handle_ = fopen( path.c_str(), appendMode ? "at" : "wt" ); + if ( !handle_ ) + { + std::cout << "Failed to create output file '" << path << "'." << std::endl; + failed_ = true; + } + } + } + + ~OutputFileHandle() + { + if ( handle_ ) + fclose( handle_ ); + } + + bool hasCreationFailed() const + { + return failed_; + } + + operator FILE *() const + { + return handle_; + } + +private: + FILE *handle_; + bool failed_; +}; + + +int __cdecl main( int argc, const char *argv[] ) +{ + std::string log; + std::string output; + std::string file; + bool noOutput; + bool noLog; + bool isSilent; + std::string input; + bool appendLog; + bool appendOutput; + Rfta::OptionsParser cmd; + cmd.addOption( 'l', "log", log, "lexer.log", "Set log path" ); + cmd.addOption( 'o', "output", output, "lexer.out", "Set output path" ); + cmd.addEnableOption( 's', "silent", isSilent, "Disable logging & output generation" ); + cmd.addOption( 'i', "input", file, "", "Set input path" ); + cmd.addDisableOption( 0, "output", noOutput, "Disable output generation" ); + cmd.addDisableOption( 0, "log", noLog, "Disable logging" ); + cmd.addIsPresentOption( 0, "log-append", appendLog, "Append to log file, don't truncate" ); + cmd.addIsPresentOption( 0, "output-append", appendOutput, "Append to output file, don't truncate" ); + try + { + cmd.parse( argc, argv ); + + if ( cmd.getPositionalCount() > 0 ) + file = cmd.getPositionalAt(0); + + if ( isSilent ) + { + noOutput = true; + noLog = true; + } + + + if ( !readInput( file, input ) ) + return 1; + } + catch ( Rfta::OptionsParserException &e ) + { + std::cout << cmd.usage( argv[0] ) << std::endl; + std::cout << e.what() << std::endl; + return 1; + } + + OutputFileHandle foutput( output, !noOutput, appendOutput ); + OutputFileHandle flog( log, !noLog, appendLog ); + if ( foutput.hasCreationFailed() || flog.hasCreationFailed() ) + return 1; + + Rfta::TokenContentManager contentManager; + Rfta::CxxParser parser; + parser.enableTrace( contentManager ); + Rfta::FileId fileId = 1234; + Rfta::TokenStream tokenStream( input.c_str(), input.c_str() + input.length(), + contentManager, + fileId ); + Rfta::CxxParser::Tokens tokens; + while ( true ) + { + unsigned int index = tokens.size(); + tokens.resize( index + 1 ); + Rfta::Token &token = tokens[index]; + tokenStream.getNextToken( token ); + if ( token.tokenId_ == Rfta::T_EOF ) + break; + } + parser.setDelegate( *new Rfta::CxxParserAction() ); + parser.initialize( tokens ); + + return 0; +} Modified: rfta/trunk/test/rftalexer_test.py =================================================================== --- rfta/trunk/test/rftalexer_test.py 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/test/rftalexer_test.py 2007-04-13 07:56:03 UTC (rev 12) @@ -21,6 +21,7 @@ return ext.lower() in ('.h', '.hpp', '.c', '.cpp', '.cc', '.cxx' ) TESTDATA_DIR = '../testdata' +TESTDATA_PROJECTS_DIR = os.path.join( TESTDATA_DIR, 'projects' ) RESULT_DIR = '../testresult' LEXER_PATH = r'..\build\test_rftalexer_Release\test_rftalexer.exe' @@ -31,7 +32,7 @@ log.close() if __name__ == '__main__': - zip_files = glob.glob( os.path.join( TESTDATA_DIR, '*.zip' ) ) + zip_files = glob.glob( os.path.join( TESTDATA_PROJECTS_DIR, '*.zip' ) ) for zip_file in zip_files: print zip_file archive = zipfile.ZipFile( zip_file, 'r' ) Modified: rfta/trunk/test/testresultbrowser.py =================================================================== --- rfta/trunk/test/testresultbrowser.py 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/test/testresultbrowser.py 2007-04-13 07:56:03 UTC (rev 12) @@ -28,6 +28,7 @@ TESTDATA_PATH = '../testdata' +TESTDATA_PROJECTS_PATH = os.path.join( TESTDATA_PATH, 'projects' ) TESTRESULT_PATH = '../testresult' PATH = '' @@ -130,7 +131,7 @@ def getSource( self, path ): source_path = path.replace('%20',' ') - zip_path = os.path.join( TESTDATA_PATH, self.project + '.zip' ) + zip_path = os.path.join( TESTDATA_PROJECTS_PATH, self.project + '.zip' ) if self.archive is None: self.archive = zipfile.ZipFile( zip_path, 'r' ) source_path = self.normalizeSourcePath( source_path ) Modified: rfta/trunk/testdata/.keepme =================================================================== --- rfta/trunk/testdata/.keepme 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/testdata/.keepme 2007-04-13 07:56:03 UTC (rev 12) @@ -1 +1 @@ -Put zipped archive of project containing source code to test in this directory. +TestData for miscellaneous tests. Added: rfta/trunk/testdata/cxxparser_ut/.keepme =================================================================== --- rfta/trunk/testdata/cxxparser_ut/.keepme (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/.keepme 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1 @@ +Sample sources for cxxparser unit tests. Added: rfta/trunk/testdata/cxxparser_ut/t000000_empty.cpp =================================================================== Added: rfta/trunk/testdata/cxxparser_ut/t001000_ns_empty.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t001000_ns_empty.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t001000_ns_empty.cpp 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,3 @@ +namespace Test +{ +} Added: rfta/trunk/testdata/cxxparser_ut/t001001_ns_nested.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t001001_ns_nested.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t001001_ns_nested.cpp 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,6 @@ +namespace Test +{ + namespace Test2 + { + } +} Added: rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty.cpp 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,3 @@ +enum T002000_E1 +{ +}; Added: rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty_anonymous.cpp =================================================================== --- rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty_anonymous.cpp (rev 0) +++ rfta/trunk/testdata/cxxparser_ut/t002000_enum_empty_anonymous.cpp 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1,3 @@ +enum +{ +}; Added: rfta/trunk/testdata/projects/.keepme =================================================================== --- rfta/trunk/testdata/projects/.keepme (rev 0) +++ rfta/trunk/testdata/projects/.keepme 2007-04-13 07:56:03 UTC (rev 12) @@ -0,0 +1 @@ +Put zipped archive of project containing source code to test in this directory. Property changes on: rfta/trunk/tools/rdpgen ___________________________________________________________________ Name: svn:ignore + *.pyc Modified: rfta/trunk/tools/rdpgen/codegenerator.py =================================================================== --- rfta/trunk/tools/rdpgen/codegenerator.py 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/tools/rdpgen/codegenerator.py 2007-04-13 07:56:03 UTC (rev 12) @@ -3,6 +3,7 @@ from sets import Set import re import sys +import os.path _HEADER_TEMPLATE = \ """#ifndef %(parser_header_guard)s @@ -606,13 +607,18 @@ import grammartokenizer import config import os.path + import os def getTokenSet(): import tokensfromtext return Set( tokensfromtext.TOKENS_BY_TEXT.values() ) # print 'using config:', sys.argv[1] - config = config.readConfigFromFile( sys.argv[1] ) + config_path = os.path.abspath(sys.argv[1]) + config_base_dir, config_name = os.path.split(config_path) + os.chdir( config_base_dir ) + print 'Using config', config_name, 'with', config_base_dir, 'as base directory.' + config = config.readConfigFromFile( config_path ) grammar_path = config.get('Grammar', 'PARSER_GRAMMAR') print 'Parsing grammar', grammar_path @@ -642,10 +648,10 @@ for name in rule_names: generator.generateRuleCode( definitions.getRuleNamed(name) ) parser_cpp_path = config.get('CodeGeneration', 'PARSER_CPP_PATH') - print 'Generating header in', parser_header_path + print 'Generating header in', os.path.abspath( parser_header_path ) header_source = repository.makeHeaderSource() file( parser_header_path, 'wt' ).write( header_source ) - print 'Generating cpp in', parser_cpp_path + print 'Generating cpp in', os.path.abspath( parser_cpp_path ) cpp_source = repository.makeImplementationSource() file( parser_cpp_path, 'wt' ).write( cpp_source ) print 'Done.' Modified: rfta/trunk/tools/rdpgen/howto.txt =================================================================== --- rfta/trunk/tools/rdpgen/howto.txt 2007-04-11 07:42:35 UTC (rev 11) +++ rfta/trunk/tools/rdpgen/howto.txt 2007-04-13 07:56:03 UTC (rev 12) @@ -25,6 +25,9 @@ '?' sub-rule Matches the sub-rule zero or one time. +'~' sub-rule +Matches anything not matched by the sub-rule. Usually used for error recovery. + '$' identifier '=' sub-rule Matches sub-rule and associates its token range to $identifier This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-11 07:42:37
|
Revision: 11 http://rfta.svn.sourceforge.net/rfta/?rev=11&view=rev Author: blep Date: 2007-04-11 00:42:35 -0700 (Wed, 11 Apr 2007) Log Message: ----------- - extracted command-line option parser from main.cpp. - added appends command-line options for log and output - added support for line continuation within string. Modified Paths: -------------- rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj rfta/trunk/makefiles/vs8/rfta.suo rfta/trunk/makefiles/vs8/test_rftalexer.vcproj.ANABELLE.Zark.user rfta/trunk/src/lib_rftaparser/lexer.re rfta/trunk/src/test_rftalexer/main.cpp rfta/trunk/test/rftalexer_test.py Added Paths: ----------- rfta/trunk/include/rfta/options.h rfta/trunk/include/rfta/options.inl Added: rfta/trunk/include/rfta/options.h =================================================================== --- rfta/trunk/include/rfta/options.h (rev 0) +++ rfta/trunk/include/rfta/options.h 2007-04-11 07:42:35 UTC (rev 11) @@ -0,0 +1,144 @@ +#ifndef RFTA_OPTIONS_H_INCLUDED +# define RFTA_OPTIONS_H_INCLUDED + +# include <cpptl/intrusiveptr.h> +# include <map> +# include <vector> +# include <string> + +namespace Rfta { + +class OptionsParserException : public std::runtime_error +{ +public: + OptionsParserException( const std::string &message ); + + virtual ~OptionsParserException() throw(); +}; + +class OptionsParser +{ +public: + class Binding : public CppTL::IntrusiveCount + { + public: + virtual ~Binding(); + + virtual void initializeToDefault() = 0; + virtual bool needParameter() = 0; + virtual void setValue( const char *value ) = 0; + virtual void setIsPresent() = 0; + }; + + typedef CppTL::IntrusivePtr<Binding> BindingPtr; + + class StringBinding : public Binding + { + public: + StringBinding( std::string &value, const std::string &defaultValue ); + public: // overridden from Binding + virtual void initializeToDefault(); + virtual bool needParameter(); + virtual void setValue( const char *value ); + virtual void setIsPresent(); + private: + std::string &value_; + std::string defaultValue_; + }; + + class IsPresentBinding : public Binding + { + public: + IsPresentBinding( bool &value, + bool hasDefaultValue, + bool defaultValue, + bool isPresentValue ); + public: // overridden from Binding + virtual void initializeToDefault(); + virtual bool needParameter(); + virtual void setValue( const char *value ); + virtual void setIsPresent(); + private: + bool &value_; + bool isPresentValue_; + bool defaultValue_; + bool hasDefaultValue_; + }; + + + void addOption( char shortName, + const char *longName, + std::string &value, + const std::string &defaultValue, + const std::string &description = std::string("") ); + + void addIsPresentOption( char shortName, + const char *longName, + bool &value, + const std::string &description = std::string(""), + bool isPresentValue = true ); + + void addEnableOption( char shortName, + const char *longName, + bool &isEnabled, + const std::string &description = std::string(""), + bool defaultValue = false ); + + void addDisableOption( char shortName, + const char *longName, + bool &isDisabled, + const std::string &description = std::string(""), + bool defaultValue = false ); + + void addBoolOptionBinding( char enableShortName, + char disableShortName, + const char *longName, + const BindingPtr &enableBinding, + const BindingPtr &disableBinding ); + + void addOptionBinding( char shortName, + const std::string &longName, + const BindingPtr &binding ); + + void addUsage( char shortName, + const std::string &longName, + const std::string &defaultValue, + const std::string &description ); + + /// @exception Throws OptionsParserException on invalid command-line + void parse( int argc, const char *argv[] ); + + std::string usage( const char *app ) const; + + void addPositionalValue( const std::string &value ); + + int getPositionalCount() const; + + const std::string &getPositionalAt( int index ) const; + + void setDefaultValues(); + + void bindValue( const BindingPtr &binding, + int argc, + int &index, + const char *argv[], + const char *valueBegin, + bool isLongOption ); + +private: + typedef std::map<char, BindingPtr> BindindsByShortName; + typedef std::map<std::string, BindingPtr> BindindsByLongName; + typedef std::vector<std::string> Positionals; + BindindsByShortName bindingsByShortName_; + BindindsByLongName bindingsByLongName_; + Positionals positionals_; + std::string usages_; + std::string shortOptions_; + std::string longOptions_; +}; + + +} // namespace Rfta { + + +#endif // RFTA_OPTIONS_H_INCLUDED Added: rfta/trunk/include/rfta/options.inl =================================================================== --- rfta/trunk/include/rfta/options.inl (rev 0) +++ rfta/trunk/include/rfta/options.inl 2007-04-11 07:42:35 UTC (rev 11) @@ -0,0 +1,364 @@ +#ifndef RFTA_OPTIONS_INL_INCLUDED +# define RFTA_OPTIONS_INL_INCLUDED + +# include "options.h" + +# ifndef RFTA_OPTIONS_API +# define RFTA_OPTIONS_API inline +# endif + +namespace Rfta { + +RFTA_OPTIONS_API +OptionsParserException::OptionsParserException( const std::string &message ) + : std::runtime_error( message ) +{ +} + + +RFTA_OPTIONS_API +OptionsParserException::~OptionsParserException() throw() +{ +} + + +RFTA_OPTIONS_API +OptionsParser::Binding::~Binding() +{ +} + + +RFTA_OPTIONS_API +OptionsParser::StringBinding::StringBinding( std::string &value, + const std::string &defaultValue ) + : value_( value ) + , defaultValue_( defaultValue ) +{ +} + + +RFTA_OPTIONS_API void +OptionsParser::StringBinding::initializeToDefault() +{ + value_ = defaultValue_; +} + +RFTA_OPTIONS_API bool +OptionsParser::StringBinding::needParameter() +{ + return true; +} + +RFTA_OPTIONS_API void +OptionsParser::StringBinding::setValue( const char *value ) +{ + value_ = value; +} + +RFTA_OPTIONS_API void +OptionsParser::StringBinding::setIsPresent() +{ +} + +RFTA_OPTIONS_API +OptionsParser::IsPresentBinding::IsPresentBinding( bool &value, + bool hasDefaultValue, + bool defaultValue, + bool isPresentValue ) + : value_( value ) + , hasDefaultValue_( hasDefaultValue ) + , defaultValue_( defaultValue ) + , isPresentValue_( isPresentValue ) +{ +} + + +RFTA_OPTIONS_API void +OptionsParser::IsPresentBinding::initializeToDefault() +{ + if ( hasDefaultValue_ ) + value_ = defaultValue_; +} + +RFTA_OPTIONS_API bool +OptionsParser::IsPresentBinding::needParameter() +{ + return false; +} + +RFTA_OPTIONS_API void +OptionsParser::IsPresentBinding::setValue( const char *value ) +{ +} + +RFTA_OPTIONS_API void +OptionsParser::IsPresentBinding::setIsPresent() +{ + value_ = isPresentValue_; +} + + + +RFTA_OPTIONS_API void +OptionsParser::addOption( char shortName, + const char *longName, + std::string &value, + const std::string &defaultValue, + const std::string &description ) +{ + BindingPtr binding( new StringBinding( value, defaultValue ) ); + addOptionBinding( shortName, longName, binding ); + addUsage( shortName, longName, "'" + defaultValue + "'", description ); +} + + +RFTA_OPTIONS_API void +OptionsParser::addIsPresentOption( char shortName, + const char *longName, + bool &value, + const std::string &description, + bool isPresentValue ) +{ + BindingPtr binding( new IsPresentBinding( value, true, !isPresentValue, isPresentValue ) ); + addOptionBinding( shortName, longName, binding ); + addUsage( shortName, longName, !isPresentValue ? "true" : "false", description ); +} + + +RFTA_OPTIONS_API void +OptionsParser::addEnableOption( char shortName, + const char *longName, + bool &isEnabled, + const std::string &description, + bool defaultValue ) +{ + BindingPtr enableBinding( new IsPresentBinding( isEnabled, true, defaultValue, true ) ); + BindingPtr disableBinding( new IsPresentBinding( isEnabled, false, false, false ) ); + addBoolOptionBinding( shortName, 0, longName, enableBinding, disableBinding ); + addUsage( shortName, longName, defaultValue ? "enabled" : "disabled", description ); +} + + +RFTA_OPTIONS_API void +OptionsParser::addDisableOption( char shortName, + const char *longName, + bool &isDisabled, + const std::string &description, + bool defaultValue ) +{ + BindingPtr enableBinding( new IsPresentBinding( isDisabled, false, false, false ) ); + BindingPtr disableBinding( new IsPresentBinding( isDisabled, true, false, true ) ); + addBoolOptionBinding( 0, shortName, longName, enableBinding, disableBinding ); + addUsage( shortName, longName, defaultValue ? "enabled" : "disabled", description ); +} + + +RFTA_OPTIONS_API void +OptionsParser::addBoolOptionBinding( char enableShortName, + char disableShortName, + const char *longName, + const BindingPtr &enableBinding, + const BindingPtr &disableBinding ) +{ + addOptionBinding( enableShortName, std::string("enable-") + longName, enableBinding ); + addOptionBinding( enableShortName, std::string("with-") + longName, enableBinding ); + addOptionBinding( enableShortName, std::string("has-") + longName, enableBinding ); + addOptionBinding( disableShortName, std::string("disable-") + longName, disableBinding ); + addOptionBinding( disableShortName, std::string("without-") + longName, disableBinding ); + addOptionBinding( disableShortName, std::string("no-") + longName, disableBinding ); +} + + +RFTA_OPTIONS_API void +OptionsParser::addOptionBinding( char shortName, + const std::string &longName, + const BindingPtr &binding ) +{ + if ( shortName != 0 ) + bindingsByShortName_[ shortName ] = binding; + if ( !longName.empty() ) + bindingsByLongName_[ longName ] = binding; +} + +RFTA_OPTIONS_API void +OptionsParser::addUsage( char shortName, + const std::string &longName, + const std::string &defaultValue, + const std::string &description ) +{ + if ( shortName ) + { + shortOptions_ += shortName; + usages_ += std::string("-") + shortName; + if ( !longName.empty() ) + usages_ += ", "; + } + else + { + usages_ += " "; + } + if ( !longName.empty() ) + { + if ( !longOptions_.empty() ) + longOptions_ += " "; + longOptions_ += "--" + longName; + usages_ += longName; + } + usages_ += "[default: " + defaultValue + "]"; + if ( !description.empty() ) + { + usages_ += ": "; + usages_ += description; + } + usages_ += "\n"; +} + +RFTA_OPTIONS_API void +OptionsParser::parse( int argc, const char *argv[] ) +{ + setDefaultValues(); + for ( int index =1; index < argc; ) + { + const char *arg = argv[index++]; + if ( arg[0] == '-' ) + { + if ( arg[1] == '-' ) // long option + { + const char *longNameEnd = &arg[2]; + const char *longNameStart = longNameEnd; + while ( *longNameEnd != 0 && *longNameEnd != '=' ) + ++longNameEnd; + std::string longName( longNameStart, longNameEnd ); + BindindsByLongName::const_iterator it = bindingsByLongName_.find( longName ); + if ( it == bindingsByLongName_.end() ) + throw OptionsParserException( "Invalid option: '" + longName + "'" ); + const BindingPtr &binding = it->second; + bindValue( binding, argc, index, argv, longNameEnd, true ); + } + else // short option + { + const char *shortOption = &arg[1]; + do + { + char shortName = *shortOption++; + BindindsByShortName::const_iterator it = bindingsByShortName_.find( shortName ); + if ( it == bindingsByShortName_.end() ) + { + throw OptionsParserException( + shortName ? (std::string("Invalid option: '") + shortName + "'") + : (std::string("Missing option: '") + arg + "'" ) ); + } + const BindingPtr &binding = it->second; + bindValue( binding, argc, index, argv, shortOption, false ); + if ( binding->needParameter() ) + break; + } + while ( *shortOption ); + } + } + else + { + addPositionalValue( arg ); + } + } +} + + +RFTA_OPTIONS_API std::string +OptionsParser::usage( const char *app ) const +{ + std::string usage = app; + usage += " "; + if ( !shortOptions_.empty() ) + usage += "-" + shortOptions_; + if ( !longOptions_.empty() ) + usage += " " + longOptions_; + usage += "\n"; + usage += usages_; + return usage; +} + + +RFTA_OPTIONS_API void +OptionsParser::addPositionalValue( const std::string &value ) +{ + positionals_.push_back( value ); +} + + +RFTA_OPTIONS_API int +OptionsParser::getPositionalCount() const +{ + return int( positionals_.size() ); +} + + +RFTA_OPTIONS_API const std::string & +OptionsParser::getPositionalAt( int index ) const +{ + return CPPTL_AT( positionals_, index ); +} + + +RFTA_OPTIONS_API void +OptionsParser::setDefaultValues() +{ + for ( BindindsByShortName::const_iterator itShort = bindingsByShortName_.begin(); + itShort != bindingsByShortName_.end(); + ++itShort ) + { + itShort->second->initializeToDefault(); + } + for ( BindindsByLongName::const_iterator itLong = bindingsByLongName_.begin(); + itLong != bindingsByLongName_.end(); + ++itLong ) + { + itLong->second->initializeToDefault(); + } +} + + +RFTA_OPTIONS_API void +OptionsParser::bindValue( const BindingPtr &binding, + int argc, + int &index, + const char *argv[], + const char *valueBegin, + bool isLongOption ) +{ + if ( binding->needParameter() ) + { + bool valueOnNextArg = false; + if ( isLongOption ) + { + if ( *valueBegin == 0 ) + valueOnNextArg = true; + else + ++valueBegin; // skip '=' + } + else if ( *valueBegin == 0 ) // short option + { + valueOnNextArg = true; + } + if ( valueOnNextArg ) + { + if ( index == argc ) + { + throw OptionsParserException( + std::string( "Missing option paramters for: '" ) + argv[index-1] + "'." ); + } + valueBegin = argv[index]; + ++index; + } + binding->setValue( valueBegin ); + } + else + { + binding->setIsPresent(); + } + +} + +} // namespace Rfta { + +#endif // RFTA_OPTIONS_INL_INCLUDED Modified: rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj =================================================================== --- rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj 2007-04-11 06:10:34 UTC (rev 10) +++ rfta/trunk/makefiles/vs8/lib_rftaparser.vcproj 2007-04-11 07:42:35 UTC (rev 11) @@ -293,7 +293,7 @@ <Tool Name="VCCustomBuildTool" Description="Generating $(InputDir)\$(InputName).cpp" - CommandLine="..\..\bin\re2c.exe -o $(InputDir)\$(InputName).cpp $(InputPath)" + CommandLine="..\..\bin\re2c.exe -o $(InputDir)\$(InputName).cpp $(InputPath)
" Outputs="$(InputDir)\$(InputName).cpp" /> </FileConfiguration> @@ -303,12 +303,20 @@ <Tool Name="VCCustomBuildTool" Description="Generating $(InputDir)\$(InputName).cpp" - CommandLine="..\..\bin\re2c.exe -o $(InputDir)\$(InputName).cpp $(InputPath)" + CommandLine="..\..\bin\re2c.exe -o $(InputDir)\$(InputName).cpp $(InputPath)
" Outputs="$(InputDir)\$(InputName).cpp" /> </FileConfiguration> </File> <File + RelativePath="..\..\include\rfta\options.h" + > + </File> + <File + RelativePath="..\..\include\rfta\options.inl" + > + </File> + <File RelativePath="..\..\src\lib_rftaparser\preprocessorlexer.cpp" > <FileConfiguration Modified: rfta/trunk/makefiles/vs8/rfta.suo =================================================================== (Binary files differ) Modified: rfta/trunk/makefiles/vs8/test_rftalexer.vcproj.ANABELLE.Zark.user =================================================================== --- rfta/trunk/makefiles/vs8/test_rftalexer.vcproj.ANABELLE.Zark.user 2007-04-11 06:10:34 UTC (rev 10) +++ rfta/trunk/makefiles/vs8/test_rftalexer.vcproj.ANABELLE.Zark.user 2007-04-11 07:42:35 UTC (rev 11) @@ -11,7 +11,7 @@ <DebugSettings Command="$(TargetPath)" WorkingDirectory="$(IntDir)" - CommandArguments="-o $(IntDir)/lexer.out -l $(IntDir)/lexer.log ../../src/test_rftalexer/test.txt" + CommandArguments="-o $(IntDir)/lexer.out -l $(IntDir)/lexer.log --log-append ../../src/test_rftalexer/test.txt" Attach="false" DebuggerType="3" Remote="1" @@ -39,7 +39,7 @@ <DebugSettings Command="$(TargetPath)" WorkingDirectory="$(IntDir)" - CommandArguments="-o$(IntDir)/lexer.out -l$(IntDir)/lexer.log ../../src/test_rftalexer/test.txt" + CommandArguments="-o$(IntDir)/lexer.out -l$(IntDir)/lexer.log --log-append ../../src/test_rftalexer/test.txt" Attach="false" DebuggerType="3" Remote="1" Modified: rfta/trunk/src/lib_rftaparser/lexer.re =================================================================== --- rfta/trunk/src/lib_rftaparser/lexer.re 2007-04-11 06:10:34 UTC (rev 10) +++ rfta/trunk/src/lib_rftaparser/lexer.re 2007-04-11 07:42:35 UTC (rev 11) @@ -12,6 +12,9 @@ - http://localhost:8666/project/scummvm-0.9.1/sources/scummvm-0.9.1/backends/dc/label.cpp#l31 => handle gcc __asm__ => tough, need to match ( ) + - http://localhost:8666/project/audacity-src-1.3.2-beta/sources/audacity-src-1.3.2-beta/lib-src/libnyquist/cmt/userio.c#l608 + => some occurrences of string escape sequence \p. What is it ? + - seems to be a gcc extension: \p become string length byte. To confirm. */ @@ -50,12 +53,13 @@ PPSpace = ([ \t]|("/*"((any\[*\n\r])*|"*"+(any\[*/\n\r])*|"\n"|"\r"|"\r\n")*"*/"))*; Pound = "#" | "??=" | "%:"; Newline = "\r\n" | "\n" | "\r"; +LineContinuation = Backslash Newline; */ /*!re2c "/*" { goto ccomment; } "//" { goto cppcomment; } - Backslash Newline { RET(T_LINECONT); } + LineContinuation { RET(T_LINECONT); } "asm" { RET(T_ASM); } "auto" { RET(T_AUTO); } @@ -263,10 +267,10 @@ ((FractionalConstant ExponentPart?) | (Digit+ ExponentPart)) FloatingSuffix? { RET(T_FLOATLIT); } - "L"? (['] (EscapeSequence|any\[\n\r\\']|UniversalChar)+ [']) + "L"? (['] (EscapeSequence|any\[\n\r\\']|UniversalChar|LineContinuation)+ [']) { RET(T_CHARLIT); } - "L"? (["] (EscapeSequence|any\[\n\r\\"]|UniversalChar)* ["]) + "L"? (["] (EscapeSequence|any\[\n\r\\"]|UniversalChar|LineContinuation)* ["]) { RET(T_STRINGLIT); } Pound PPSpace "include" PPSpace "<" (any\[\n\r>])+ ">" Modified: rfta/trunk/src/test_rftalexer/main.cpp =================================================================== --- rfta/trunk/src/test_rftalexer/main.cpp 2007-04-11 06:10:34 UTC (rev 10) +++ rfta/trunk/src/test_rftalexer/main.cpp 2007-04-11 07:42:35 UTC (rev 11) @@ -1,15 +1,12 @@ #include <rfta/lexer.h> #include <rfta/cpptokens.h> -#include <cpptl/intrusiveptr.h> +#include <rfta/options.inl> #include <cpptl/scopedptr.h> #include <cpptl/stringtools.h> #include <algorithm> #include <fstream> #include <iostream> #include <stdexcept> -#include <map> -#include <string> -#include <vector> #include <stdio.h> /* Test program: @@ -17,352 +14,6 @@ - output synthesis on stdout. */ - - -class CommandLineParserException : public std::runtime_error -{ -public: - CommandLineParserException( const std::string &message ) - : std::runtime_error( message ) - { - } - - virtual ~CommandLineParserException() throw() - { - } -}; - -class CommandLineParser -{ -public: - class Binding : public CppTL::IntrusiveCount - { - public: - virtual ~Binding() - { - } - - virtual void initializeToDefault() = 0; - virtual bool needParameter() = 0; - virtual void setValue( const char *value ) = 0; - virtual void setIsPresent() = 0; - }; - - typedef CppTL::IntrusivePtr<Binding> BindingPtr; - - class StringBinding : public Binding - { - public: - StringBinding( std::string &value, const std::string &defaultValue ) - : value_( value ) - , defaultValue_( defaultValue ) - { - } - public: // overridden from Binding - virtual void initializeToDefault() - { - value_ = defaultValue_; - } - - virtual bool needParameter() - { - return true; - } - - virtual void setValue( const char *value ) - { - value_ = value; - } - - virtual void setIsPresent() - { - } - private: - std::string &value_; - std::string defaultValue_; - }; - - class IsPresentBinding : public Binding - { - public: - IsPresentBinding( bool &value, - bool hasDefaultValue, - bool defaultValue, - bool isPresentValue ) - : value_( value ) - , hasDefaultValue_( hasDefaultValue ) - , defaultValue_( defaultValue ) - , isPresentValue_( isPresentValue ) - { - } - public: // overridden from Binding - virtual void initializeToDefault() - { - if ( hasDefaultValue_ ) - value_ = defaultValue_; - } - - virtual bool needParameter() - { - return false; - } - - virtual void setValue( const char *value ) - { - } - - virtual void setIsPresent() - { - value_ = isPresentValue_; - } - private: - bool &value_; - bool isPresentValue_; - bool defaultValue_; - bool hasDefaultValue_; - }; - - - - void addOption( char shortName, - const char *longName, - std::string &value, - const std::string &defaultValue, - const std::string &description = std::string("") ) - { - BindingPtr binding( new StringBinding( value, defaultValue ) ); - addOptionBinding( shortName, longName, binding ); - addUsage( shortName, longName, "'" + defaultValue + "'", description ); - } - - void addEnableOption( char shortName, - const char *longName, - bool &isEnabled, - const std::string &description = std::string(""), - bool defaultValue = false ) - { - BindingPtr enableBinding( new IsPresentBinding( isEnabled, true, defaultValue, true ) ); - BindingPtr disableBinding( new IsPresentBinding( isEnabled, false, false, false ) ); - addBoolOptionBinding( shortName, 0, longName, enableBinding, disableBinding ); - addUsage( shortName, longName, defaultValue ? "enabled" : "disabled", description ); - } - - void addDisableOption( char shortName, - const char *longName, - bool &isDisabled, - const std::string &description = std::string(""), - bool defaultValue = false ) - { - BindingPtr enableBinding( new IsPresentBinding( isDisabled, false, false, false ) ); - BindingPtr disableBinding( new IsPresentBinding( isDisabled, true, false, true ) ); - addBoolOptionBinding( 0, shortName, longName, enableBinding, disableBinding ); - addUsage( shortName, longName, defaultValue ? "enabled" : "disabled", description ); - } - - void addBoolOptionBinding( char enableShortName, - char disableShortName, - const char *longName, - const BindingPtr &enableBinding, - const BindingPtr &disableBinding ) - { - addOptionBinding( enableShortName, std::string("enable-") + longName, enableBinding ); - addOptionBinding( enableShortName, std::string("with-") + longName, enableBinding ); - addOptionBinding( enableShortName, std::string("has-") + longName, enableBinding ); - addOptionBinding( disableShortName, std::string("disable-") + longName, disableBinding ); - addOptionBinding( disableShortName, std::string("without-") + longName, disableBinding ); - addOptionBinding( disableShortName, std::string("no-") + longName, disableBinding ); - } - - void addOptionBinding( char shortName, - const std::string &longName, - const BindingPtr &binding ) - { - if ( shortName != 0 ) - bindingsByShortName_[ shortName ] = binding; - if ( !longName.empty() ) - bindingsByLongName_[ longName ] = binding; - } - - void addUsage( char shortName, - const std::string &longName, - const std::string &defaultValue, - const std::string &description ) - { - if ( shortName ) - { - shortOptions_ += shortName; - usages_ += std::string("-") + shortName; - if ( !longName.empty() ) - usages_ += ", "; - } - else - { - usages_ += " "; - } - if ( !longName.empty() ) - { - if ( !longOptions_.empty() ) - longOptions_ += " "; - longOptions_ += "--" + longName; - usages_ += longName; - } - usages_ += "[default: " + defaultValue + "]"; - if ( !description.empty() ) - { - usages_ += ": "; - usages_ += description; - } - usages_ += "\n"; - } - - /// @exception Throws CommandLineParserException on invalid command-line - void parse( int argc, const char *argv[] ) - { - setDefaultValues(); - for ( int index =1; index < argc; ) - { - const char *arg = argv[index++]; - if ( arg[0] == '-' ) - { - if ( arg[1] == '-' ) // long option - { - const char *longNameEnd = &arg[2]; - const char *longNameStart = longNameEnd; - while ( *longNameEnd != 0 && *longNameEnd != '=' ) - ++longNameEnd; - std::string longName( longNameStart, longNameEnd ); - BindindsByLongName::const_iterator it = bindingsByLongName_.find( longName ); - if ( it == bindingsByLongName_.end() ) - throw CommandLineParserException( "Invalid option: '" + longName + "'" ); - const BindingPtr &binding = it->second; - bindValue( binding, argc, index, argv, longNameEnd, true ); - } - else // short option - { - const char *shortOption = &arg[1]; - do - { - char shortName = *shortOption++; - BindindsByShortName::const_iterator it = bindingsByShortName_.find( shortName ); - if ( it == bindingsByShortName_.end() ) - { - throw CommandLineParserException( - shortName ? (std::string("Invalid option: '") + shortName + "'") - : (std::string("Missing option: '") + arg + "'" ) ); - } - const BindingPtr &binding = it->second; - bindValue( binding, argc, index, argv, shortOption, false ); - if ( binding->needParameter() ) - break; - } - while ( *shortOption ); - } - } - else - { - addPositionalValue( arg ); - } - } - } - - std::string usage( const char *app ) const - { - std::string usage = app; - usage += " "; - if ( !shortOptions_.empty() ) - usage += "-" + shortOptions_; - if ( !longOptions_.empty() ) - usage += " " + longOptions_; - usage += "\n"; - usage += usages_; - return usage; - } - - void addPositionalValue( const std::string &value ) - { - positionals_.push_back( value ); - } - - int getPositionalCount() const - { - return int( positionals_.size() ); - } - - const std::string &getPositionalAt( int index ) const - { - return CPPTL_AT( positionals_, index ); - } - -private: - void setDefaultValues() - { - for ( BindindsByShortName::const_iterator itShort = bindingsByShortName_.begin(); - itShort != bindingsByShortName_.end(); - ++itShort ) - { - itShort->second->initializeToDefault(); - } - for ( BindindsByLongName::const_iterator itLong = bindingsByLongName_.begin(); - itLong != bindingsByLongName_.end(); - ++itLong ) - { - itLong->second->initializeToDefault(); - } - } - - /// @exception Throws CommanlineParserException on failure - void bindValue( const BindingPtr &binding, - int argc, - int &index, - const char *argv[], - const char *valueBegin, - bool isLongOption ) - { - if ( binding->needParameter() ) - { - bool valueOnNextArg = false; - if ( isLongOption ) - { - if ( *valueBegin == 0 ) - valueOnNextArg = true; - else - ++valueBegin; // skip '=' - } - else if ( *valueBegin == 0 ) // short option - { - valueOnNextArg = true; - } - if ( valueOnNextArg ) - { - if ( index == argc ) - { - throw CommandLineParserException( - std::string( "Missing option paramters for: '" ) + argv[index-1] + "'." ); - } - valueBegin = argv[index]; - ++index; - } - binding->setValue( valueBegin ); - } - else - { - binding->setIsPresent(); - } - - } - - typedef std::map<char, BindingPtr> BindindsByShortName; - typedef std::map<std::string, BindingPtr> BindindsByLongName; - typedef std::vector<std::string> Positionals; - BindindsByShortName bindingsByShortName_; - BindindsByLongName bindingsByLongName_; - Positionals positionals_; - std::string usages_; - std::string shortOptions_; - std::string longOptions_; -}; - - static bool readInput( const std::string &file, std::string &input ) @@ -393,12 +44,14 @@ class OutputFileHandle { public: - OutputFileHandle( const std::string &path, bool create, const char *mode ) + OutputFileHandle( const std::string &path, + bool create, + bool appendMode ) { failed_ = false; if ( create ) { - handle_ = fopen( path.c_str(), mode ); + handle_ = fopen( path.c_str(), appendMode ? "at" : "wt" ); if ( !handle_ ) { std::cout << "Failed to create output file '" << path << "'." << std::endl; @@ -438,13 +91,17 @@ bool noLog; bool isSilent; std::string input; - CommandLineParser cmd; + bool appendLog; + bool appendOutput; + Rfta::OptionsParser cmd; cmd.addOption( 'l', "log", log, "lexer.log", "Set log path" ); cmd.addOption( 'o', "output", output, "lexer.out", "Set output path" ); cmd.addEnableOption( 's', "silent", isSilent, "Disable logging & output generation" ); cmd.addOption( 'i', "input", file, "", "Set input path" ); cmd.addDisableOption( 0, "output", noOutput, "Disable output generation" ); cmd.addDisableOption( 0, "log", noLog, "Disable logging" ); + cmd.addIsPresentOption( 0, "log-append", appendLog, "Append to log file, don't truncate" ); + cmd.addIsPresentOption( 0, "output-append", appendOutput, "Append to output file, don't truncate" ); try { cmd.parse( argc, argv ); @@ -462,15 +119,15 @@ if ( !readInput( file, input ) ) return 1; } - catch ( CommandLineParserException &e ) + catch ( Rfta::OptionsParserException &e ) { std::cout << cmd.usage( argv[0] ) << std::endl; std::cout << e.what() << std::endl; return 1; } - OutputFileHandle foutput( output, !noOutput, "wt" ); - OutputFileHandle flog( log, !noLog, "at" ); + OutputFileHandle foutput( output, !noOutput, appendOutput ); + OutputFileHandle flog( log, !noLog, appendLog ); if ( foutput.hasCreationFailed() || flog.hasCreationFailed() ) return 1; Modified: rfta/trunk/test/rftalexer_test.py =================================================================== --- rfta/trunk/test/rftalexer_test.py 2007-04-11 06:10:34 UTC (rev 10) +++ rfta/trunk/test/rftalexer_test.py 2007-04-11 07:42:35 UTC (rev 11) @@ -50,7 +50,7 @@ source = archive.read( source_path ) print 'Parsing', source_path appendToLog( outfile_log, "#SOURCELOG: " + source_path ) - cmd = ( LEXER_PATH, '-o', outfile_lexer, '-l', outfile_log ) + cmd = ( LEXER_PATH, '-o', outfile_lexer, '-l', outfile_log, '--log-append' ) try: ## print 'Running', cmd process = subprocess.Popen( cmd, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-11 06:10:35
|
Revision: 10 http://rfta.svn.sourceforge.net/rfta/?rev=10&view=rev Author: blep Date: 2007-04-10 23:10:34 -0700 (Tue, 10 Apr 2007) Log Message: ----------- - Added some old resources. Modified Paths: -------------- rfta/trunk/makefiles/vs8/rfta.suo Added Paths: ----------- rfta/trunk/resources/ rfta/trunk/resources/DataStructureForC++.doc rfta/trunk/resources/cpp_grammar.txt rfta/trunk/resources/prepro_algo.txt Property Changed: ---------------- rfta/trunk/ rfta/trunk/makefiles/vs8/ rfta/trunk/src/lib_rftaparser/ Property changes on: rfta/trunk ___________________________________________________________________ Name: svn:ignore + build Property changes on: rfta/trunk/makefiles/vs8 ___________________________________________________________________ Name: svn:ignore + rfta.ncb Modified: rfta/trunk/makefiles/vs8/rfta.suo =================================================================== (Binary files differ) Property changes on: rfta/trunk/resources ___________________________________________________________________ Name: svn:ignore + c++doc Added: rfta/trunk/resources/DataStructureForC++.doc =================================================================== (Binary files differ) Property changes on: rfta/trunk/resources/DataStructureForC++.doc ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: rfta/trunk/resources/cpp_grammar.txt =================================================================== --- rfta/trunk/resources/cpp_grammar.txt (rev 0) +++ rfta/trunk/resources/cpp_grammar.txt 2007-04-11 06:10:34 UTC (rev 10) @@ -0,0 +1,768 @@ +# Syntax: +# '#' any on the line for one line comment +# $token_type matches 1 occurence of the specified token type +# ( @string matches a string, @float a float...) +# '...' matches 1 occurrence of the 'symbol' token type with the specified text +# %'... ...' matches 1 occurrence of one of the symbol specified in the text. +# Symbols must be separated by exactly one space ( %'true false' will +# match either the token symbol 'true' or 'false'. +# @node_name( ... ) braced expression tokens become children of a node which +# name is specified by 'node_name'. +# $token_type( '...' ) matches 1 occurrence of the specified token with +# the specified type. +# list( expression, separator_expression ) predefined parametrized parser +# :rename_last_node( '...' ) +# parser_name = ... ';' declare a parser with the specified name matches the expression +# on the right side of '='. A parser name may be declared only once +# parser_name(.p1,.p2,...) = ... declare a parametrized parser with the specified name +# matches the expression on the right side of '='. A parser name may +# be declared only once. '.p1' are the expression passed as parameter +# of the parser. +# parser_name matches the expression specified in the declaration of 'parser_name'. +# A parser may be referenced before being declared, but all references +# must be resolved. +# parser_name(p1,p2,...) matched the expression specified in the declaration of +# the parametrized parser 'parser_name'. p1, p2, ... are passed as parameters. +# ... ... matches the specified sequence. +# ... || ... matches either the left side expression or the right side expression. +# All expressions are tested for matching and the longuest is kept as +# a matched (the one that matched the most important number of tokens). +# ... | ... matches either the left side expression or the right side expression. +# If the left side expression is matched, then the right side expression +# is not tested for matching. +# '[' ... ']' matches the braced expression. +# ?( ... ) matches 0 or 1 occurence of the braced expression +# +( ... ) matches 1 or more occurrences of the braced expression +# *( ... ) matches 0 or more occurrences of the braced expression +# %('... ...' '... ...') matches 1 occurrence of one of the symbol specified in the text. +# Symbols must be separated by exactly one space ( %'true false' will +# match either the token symbol 'true' or 'false'. +# !( ... ) fail if the inner expression is matched +# Operators priority: +# sequence, longuest alternative, first alternative +# +# Commands: +# :node( name, matcher ) create a new node which children are the specified matcher production +# :rename( name ) rename the 'current' node +# :rename_last_child( name ) rename the last child node +# :new_node(name) create a new node with the specified name. Next matched token will be first child. +# :save_node() push the current node on the memory stack +# :restore_node() pop the last node from the memory stack +# :make_penultimate_node_child_of_last() make the penultimate node child of the last node +# :remove_last_child remove the last node + +::TokenType + $symbol + $spaces + $identifier + $string + $character + $integer + $float + $cpp_comment + $c_comment + $error + +::Grammar + +# Additional commands available: +# :cpp_block_error_recovery(): skip all tokens until the end of the statement is found. +# The end of the statement is: +# - closing of the current declaration block (non nested '}' found) +# - a non nested ';' found +# - no more token available (end of input) + +list(.item,.sep) = .item *(.sep .item); + +list_min2(.item,.sep) = .item .sep .item *(.sep .item); + +binary_operator(.left_operand,.right_operand_node) = + .left_operand *( .right_operand_node :make_penultimate_node_child_of_last() ) + ; + +make_right_operand(.name,.operand) = :node(.name, .operand ); + +# Used parse sequence where the first element is optional and can not be distinguished +# from the mandatory part. +optional_alternative(.optional, .mandatory) = .optional .mandatory | .mandatory; + + +# ############################## A.4: Program ############################ +# A.4, C++PL3 p.798 + +translation_unit = :node( 'translation_unit', declaration_seq ); + + +# ############################## A.5: Expressions ############################ +# A.5, C++PL3 p.798-802 + +literal_expression = :node('literal', + $integer + | '0' + | $character + | $string + | $float + | %'true false' + ); + +id = $identifier; + +namespace_name = id; + +class_or_namespace_name = class_name; # | namespace_name; + +template_name_specifier = 'template' nested_name_specifier; + +nested_name_specifier = +( class_or_namespace_name '::' ?(template_name_specifier) ); + + +# Notes: qualified_id can not include 'template' => A::template B::zozo is not parsed (IT SHOULD BE) +qualified_id = :node( 'qualified_id', + ?('::') nested_name_specifier ?('template') unqualified_id + | [ '::' [ id + | operator_function_id + | conversion_function_id ] + ] ); + + +# Notes: template id not included +# destructor_ref may be parsed as such while it is not a reference to a destructor (overloaded ~ operator & ()) +unqualified_id = id + | operator_function_id + | conversion_function_id + | :node( 'destructor_ref', '~' id ??( '(' ')' ) ) + ; + +id_expression = qualified_id + || :node( 'unqualified_id', unqualified_id ) + ; + +# C++ Standard p65 +primary_expression = literal_expression + | :node('this_ref', 'this' ) + | :node('braced_expr', '(' expression ')' ) + | :node('id_expression', id_expression ) + ; + +# Notes: not included in postfix_expression_p: +# typename with template in scope +# +# postfix_expression_p as been modified to avoid the infinite left recursion. This recursion has been +# moved to multiple 'optional' suffixes +# + +array_operator_suffix = :node('array_index', '[' expression ']'); + +call_operator_suffix = :node('call_parameters', '(' ?( expression_list ) ')'); + +# Notes: missing template in scope case +pseudo_destructor_name = :node( 'pseudo_destructor_name', + ?('::') ?(nested_name_specifier) ?(class_name '::') '~' id ); # type_name + +accessed_member = pseudo_destructor_name + | [ ?( 'template' ) ?('::') id_expression ] + ; + +instance_accessor = %'. ->'; + +member_access_suffix = :node('accessed_member', instance_accessor accessed_member ); + +post_incdec_suffix = :node( 'post_operator', %'++ --' ); + + +cast_keywords = %'dynamic_cast static_cast reinterpret_cast const_cast'; + +cppcast_expression = :node('cppcast_expression', + cast_keywords '<' type_id '>' '(' expression ')' ); + +type_id_expression = :node('typeid_expression', + 'typeid' '(' [type_id | expression] ')' ); + + +# Notes: because of the typeless parsing a function call can not be distinguished from a +# functional type conversion. In the case of a function call, the name of the function will be found in the +# type id. +call_or_conversion_expression = :node( 'call_or_conversion_expression', + [ ['typename' ?('::') nested_name_specifier id] + | simple_type_specifier + ] '(' ?( expression_list ) ')' ); + +#Notes: template_id construction is missing +postfix_expression = binary_operator( + cppcast_expression + | type_id_expression + | call_or_conversion_expression + | primary_expression, + make_right_operand( 'array_access', array_operator_suffix ) + | make_right_operand( 'call', call_operator_suffix ) + | make_right_operand( 'member_access', member_access_suffix ) + | make_right_operand( 'post_incdec', post_incdec_suffix ) ); + + +cast_expression = unary_expression + | :node('cast_expression', + '(' type_id ')' :node('casted_expression', + cast_expression ) ) + ; + +delete_expression = :node( 'delete_operator', + ?( '::') 'delete' ?( '[' ']' ) cast_expression ) + ; + +new_initializer = :node('new_initializer', '(' ?( expression_list ) ')'); + + +direct_new_declarator = +( '[' expression ']' ) + ?( '[' constant_expression ']' ) + ; + +new_declarator = [ ptr_operator ?( new_declarator ) ] + | direct_new_declarator + ; + +new_type_id = :node( 'new_type_id', new_type ?( new_declarator ) ); +new_type_id_alt = [ '(' new_type_id ')' ] + | new_type_id + ; + +new_placement = :node('new_placement', '(' expression_list ')'); + +new_expression = :node('new_operator', + ?( '::' ) 'new' + optional_alternative( new_placement, + new_type_id_alt ?(new_initializer) ) ); + +# Notes: added '++' & '--' +unary_operator = %'++ -- * & + - ! ~'; + +# Notes: sizeof( expr ) is already handled because unary_expression may be a braced expression. +unary_expression = postfix_expression + | :node('unary_operator', unary_operator cast_expression) + | :node('sizeof_operator', 'sizeof' unary_expression) + | new_expression + | delete_expression; + + +pm_expression = binary_operator( cast_expression, + make_right_operand( 'pointer_to_member_operator', + :node('right_operand', instance_accessor '*' cast_expression ) ) ); + +binary_expression(.simple_expression,.operators) = binary_operator( + .simple_expression, + make_right_operand( 'binary_operator', .operators .simple_expression ) ); + +multiplicative_expression = binary_expression( pm_expression, %'* / %' ); +additive_expression = binary_expression( multiplicative_expression, %'+ -' ); +shift_expression = binary_expression( additive_expression, %'<< >>' ); +relational_expression = binary_expression( shift_expression, %'< > <= >=' ); +equality_expression = binary_expression( relational_expression, %'== !=' ); +and_expression = binary_expression( equality_expression, %'&' ); +exclusive_or_expression = binary_expression( and_expression, '^' ); +inclusive_or_expression = binary_expression( exclusive_or_expression, '|' ); +logical_and_expression = binary_expression( inclusive_or_expression, '&&' ); +logical_or_expression = binary_expression( logical_and_expression, '||' ); + +conditional_expression = binary_operator( + logical_or_expression, + make_right_operand( 'tertiary_operator', + '?' expression ':' assignment_expression ) + ); + +assignment_operator = %'= *= /= %= += -= >>= <<= &= ^= |='; + +#assignment_operation = +assignment_operation = :node( 'assignment_operator', + logical_or_expression assignment_operator assignment_expression ); + +assignment_expression_intern = + conditional_expression + || assignment_operation + || throw_expression + ; + +expression = :node( 'expression', + :node( 'assignment_expression_list', list_min2( assignment_expression_intern, ',' ) ) + | assignment_expression_intern ); + +assignment_expression = :node( 'assignment_expression', assignment_expression_intern ); + +constant_expression = :node( 'constant_expression', conditional_expression ); + +expression_list = :node( 'expression_list', list( assignment_expression, ',' ) ); + + +# ############################## A.6: Statements ############################ +# A.6, C++PL3 p.802-803 + +condition = expression + | [ type_specifier declarator '='assignment_expression ] + ; + +expression_statement = :node( 'expression_statement', ?(expression) ';' ); + +jump_statement = :node( 'break_statement', 'break' ';' ) + | :node( 'continue_statement', 'continue' ';' ) + | :node( 'return_statement', 'return' ?(expression) ';') + | :node( 'goto_statement', 'goto' id ';') + ; + +for_init_statement = :node( 'for_init_statement', + expression_statement + | simple_declaration ) + ; + +iteration_statement = :node('while_statement', + 'while' '(' condition ')' statement ) + | :node('dowhile_statement', + 'do' statement 'while' '(' expression ')' ';' ) + | :node('for_statement', + 'for' '(' for_init_statement + ?( :node('for_condition', condition ) ) + ';' ?( expression ) ')' + :node('for_loop_statement', statement) ) + ; + +selection_statement = :node( 'if_statement', + 'if' '(' :node('condition', condition) ')' + :node('then_statement', statement) + ?( 'else' :node('else_statement', statement) ) ) + | :node( 'switch_statement', + 'switch' '(' :node('condition', condition) ')' + :node('condition_statement', statement) ) + ; + +error_recovery_statement = :node( 'error_statement', :cpp_block_error_recovery() ); + +compound_statement = :node( 'compound_statement', + '{' *( ??( !('}') ) [statement | error_recovery_statement] ) '}' ); +# optimized: added look-ahead for end of compound +# '{' *( statement | error_recovery_statement ) '}' ); + +target_statement = ':' :node('target_statement', statement ); + +labeled_statement = :node('label_statement', id target_statement ) + | :node('case_statement', 'case' constant_expression target_statement ) + | :node('default_statement', 'default' target_statement ); + +declaration_statement = :node( 'declaration_statement', block_declaration ); + +statement = labeled_statement + | compound_statement + | selection_statement + | iteration_statement + | jump_statement + | expression_statement + | declaration_statement + | try_block + ; + + +# ############################## A.7: Declaration ############################ + +declaration_error_recovery = :node( 'declaration_error', :cpp_block_error_recovery() ); + +declaration_seq = :node('declarations', *( declaration | declaration_error_recovery ) ); + +# A.7, C++PL3 p.805-806 +# => parse namespace declaration and namespace alias declaration +# Notes: OK. No parsing issue +qualified_namespace_specifier = :node( 'namespace_specifier', + ?('::') *(id '::') namespace_name ); +namespace_body = '{' declaration_seq '}'; +named_namespace_definition = 'namespace' id namespace_body; +unnamed_namespace_definition = 'namespace' namespace_body; +namespace_definition = :node( 'named_namespace_def', named_namespace_definition ) + | :node( 'unnamed_namespace_def', unnamed_namespace_definition ) + ; +namespace_alias_definition = :node('namespace_alias_def', + 'namespace' id '=' qualified_namespace_specifier ';' ); + +# A.7, C++PL3 p.806 +# => parse using declaration and directive +# Notes: OK. No parsing issue +using_id = :node( 'using_id', + [ ?('typename') ?('::') nested_name_specifier unqualified_id ] + | [ ?('::') unqualified_id ] ); +using_declaration = :node('using_declaration', 'using' using_id ';' ); + +using_directive = :node( 'using_directive', + 'using' 'namespace' qualified_namespace_specifier ';' ); + +# A.7, C++PL3 p.806 +# => parse asm definition (__asm) => Microsoft Visual C++ +asm_keyword = %'asm __asm'; + +asm_definition = :node( 'asm_definition', asm_keyword '(' $string ')' ';' ); + +# A.7, C++PL3 p.806 +# => parse extern specifiction +linkage_specification_begin = 'extern' $string; +linkage_specification = :node( 'linkage_specification', + linkage_specification_begin [ [ '{' declaration_seq '}' ] + | declaration ] ); + +# A.7, C++PL3 p.804-806 +# => parse simple declaration +# Notes: parsing issue in: +# -simple_type_specifier_p +# -enumerator_definition_p (for constant expression that contains template with multiple parameters) + +enumerator = id; + +enumerator_definition = :node( 'enumerator_definition', + enumerator ?( '=' constant_expression ) ); + +enum_specifier = :node( 'enum_specifier', + 'enum' ?(id) '{' + :node( 'enumerator_definitions', + ?( list(enumerator_definition, ',') ) ) + '}' ); + +forwarded_type_id = :node( 'forwarded_type_id', + ?( '::' ) ?( nested_name_specifier ) id ); +forward_typename_id = :node( 'forwarded_type_id', + ?( '::' ) ?( nested_name_specifier ) [ [ 'template' template_id ] + | id ] ); + +elaborated_type_specifier = + :node( 'forward_class_specifier', class_key forwarded_type_id ) + | :node( 'forward_enum_specifier', 'enum' forwarded_type_id ??( !('(') ) ) + | :node( 'forward_typename_specifier', 'typename' forward_typename_id ??( !('(') ) ); + +fundamental_type = +( %'char wchar_t bool short int long signed unsigned float double void' ); + +# Notes: possible optimization issue for type_name => may need longuest_f +user_type_specifier = + :node( 'type_name', ?('::') nested_name_specifier ?('template') template_id ) + | :node( 'type_name', ?('::') ?(nested_name_specifier) type_name ); + +simple_type_specifier = :node( 'fundamental_type_specifier', fundamental_type ) + | user_type_specifier; + +msvc_declspec = :node( 'msvc_declspec', '__declspec' '(' $identifier ')' ); + +storage_class_specifier = :node('storage_class_specifier', + msvc_declspec %'auto register static extern mutable' + | msvc_declspec ); +function_specifier = :rename('function_specifier') %'inline virtual explicit'; + +# Hand made rules concerning the order of decl_specifier +# Those rules allow us to detect that the type specifier of 'MyClass instance' is 'MyClass' +# and not 'MyClass insance'. +# typedef cv_qualifiers type cv_qualifiers +# storage_class_specifier(1) function_specifiers cv_qualifiers type cv_qualifiers +# friend 'storage decl' +# type = repeat(1,base_type) | user_type +##decl_specifiers_p = buggy # :node( 'decl_specifiers', repeat_f( 1, decl_specifier_p ) ) + +constructor_type_specifier = ?( :node('declaration_specifier', function_specifier) ); + +workaround_type_specifier = simple_type_specifier + | enum_specifier + | [ class_specifier + || elaborated_type_specifier ]; + +standard_decl_specifier_impl = ?( storage_class_specifier ) + ?( function_specifier ) type_specifier; + +standard_decl_specifiers = :node( 'declaration_specifier', standard_decl_specifier_impl ); + +typedef_decl_specifiers = :node( 'typedef_specifier', + 'typedef' type_specifier ); + +friend_decl_specifiers = :node( 'friend_specifier', + 'friend' standard_decl_specifier_impl ); + +decl_specifiers = typedef_decl_specifiers + | friend_decl_specifiers + | standard_decl_specifiers; + +simple_declaration = :node( 'simple_declaration', + ?( decl_specifiers ) ?('__cdecl') ?( init_declarator_list ) ';' ); + +# A.7, C++PL3 p.804 +block_declaration = asm_definition + | namespace_alias_definition + | using_declaration + | using_directive + | simple_declaration; + +declaration = block_declaration + | linkage_specification + | namespace_definition + | function_definition + | template_declaration + | explicit_instantiation + | explicit_specialization + ; + + +# ############################## A.7.1: Declarators ############################ +# A.7.1, C++PL3 p.807-808 + +cv_qualifier = %'const volatile'; +cv_qualifier_seq = :node( 'cv_qualifiers', +( cv_qualifier ) ); + +# buggy standard C++ rules. Use 'custom type parser instead' => see decl_specifiers_p, parameter_type_p, +# new_type_pi, function_return_type... +# decl_specifier_seq_p = buggy # repeat_f( 1, decl_specifier_p ) +# decl_specifier_p = buggy #( storage_class_specifier_p +# | type_specifier_p +# | function_specifier_p +# | rename_f( 'friend_specifier', 'friend' ) +# | rename_f( 'typedef_specifier', 'typedef' ) ) +# type_specifier_p = buggy #( simple_type_specifier_p +# | enum_specifier_p +# | longuest_f( class_specifier_pi, elaborated_type_specifier_p ) +# | cv_qualifier_p) + + +# removed left recursion +direct_abstract_declarator_fn_suffix = + :node( 'function_parameters', '(' parameter_declaration_clause ')' ) + ?( cv_qualifier_seq ) ?( exception_specification ) + ; + +direct_abstract_declarator_array_suffix = :node( 'abstract_array_declarator', + '[' ?( constant_expression ) ']' ); + +direct_abstract_declarator = + ?( '(' abstract_declarator ')' ) + *( direct_abstract_declarator_fn_suffix + | direct_abstract_declarator_array_suffix ) + ; + +abstract_declarator = [ ptr_operator ?( abstract_declarator ) ] + | direct_abstract_declarator; + +opt_parameter_decl_assign = ?( :node( 'assign_initializer', '=' assignment_expression ) ); + +new_type = workaround_type_specifier; + +parameter_declaration = :node( 'function_parameter', + :node('declaration_specifier', type_specifier) + :node('declarator', declarator | abstract_declarator) + opt_parameter_decl_assign ); + +ellipsis_parameter_declaration = :node('ellipsis_parameter', '...' ); + +parameter_declaration_clause = ellipsis_parameter_declaration + | [ ?( list( parameter_declaration, ',' ) ) + ?( ',' ellipsis_parameter_declaration ) ] + ; + +enum_name = id; + +typedef_name = id; # p793 + +# optimization: all three are identical during parsing +#type_name = class_name | enum_name | typedef_name; +type_name = class_name; + +# Notes: simplified, alternatives are redondant in typeless context +declarator_id = :node( 'declarator_id', ?( '::' ) id_expression ); + +ptr_operator = [ '*' ?( cv_qualifier_seq ) ] + | '&' + | :node('pointer_to_member', + ?('::') nested_name_specifier '*' ?( cv_qualifier_seq ) ) + ; + +# defined in A71, declarators, p807 , after cv_qualifier +type_id = :node( 'type_id', type_specifier ?( abstract_declarator ) ); + +# removed infinite left recursion +direct_declarator = [ declarator_id + | :node('braced_declarator', '(' declarator ')') + ] *( direct_abstract_declarator_fn_suffix + | direct_abstract_declarator_array_suffix ) + ; + +# Notes: inversed order to parse pointer to member correctly. +# simplified => introduced repetition of ptr and discarded alternative +#declarator_p.setParser( (ptr_operator_pi >> declarator_p) +# | direct_declarator_p ) +declarator = ?( :node( 'ptr_operator_declarator', +( ptr_operator ) ) ) direct_declarator; + +initializer_list = list( initializer_clause, ',' ); + +initializer_clause = assignment_expression + | [ '{' ?( initializer_list ?( ',' ) ) '}' ]; + +initializer = :node('assign_initializer', '=' initializer_clause ) + | [ '(' expression_list ')' ]; + +init_declarator = :node( 'init_declarator', + :node('declarator', declarator) ?( initializer ) ); + +init_declarator_list = :node( 'init_declarators', list( init_declarator, ',' ) ); + +type_specifier = :node( 'type_specifier', + ?(cv_qualifier_seq) workaround_type_specifier + ?(cv_qualifier_seq) ); + +function_body = compound_statement; + +#Note: C++ standard, p140: +# a declarator_p in a function definition shall have the form: +# D1 ( parameter_declaration_clause ) optional_f(cv_qualifier_seq) optional_f(exception_specification) +# function_declarator_p implement this instead of using a standard declarator_p. + +# fixed bug: added support for pointer return types +function_return_type = type_specifier + ?( :node( 'ptr_operator_declarator', +( ptr_operator ) ) ); + +function_declarator = declarator_id direct_abstract_declarator_fn_suffix; +function_definition_start = optional_alternative( + :node( 'function_return_type', function_return_type ), + function_declarator ); +function_definition = :node('function_definition', + function_definition_start [ [ ?(ctor_initializer) function_body] + | function_try_block ] ); + + +# ############################## A.8: Classes ############################ +# A.8, C++PL3 p.808-809 + +class_name = id; + +constant_initializer = '=' constant_expression; + +pure_specifier = :node( 'pure_specifier', '=' '0' ); + +# added, somehow the original grammar is not parsing this +constructor_declaration = constructor_type_specifier function_declarator; + +member_declarator = [ :node('declarator', declarator) ?(pure_specifier) ] + || [ :node('declarator', declarator) ?(constant_initializer) ] + || [ ?(id) ':' constant_expression ]; + +member_declarator_list = list( member_declarator, ',' ); + +#Notes: not included: +#- opt(::) nested-name-specifier opt(template) unqualified-id +member_declaration = + :node( 'member_function_definition', function_definition ?(';') ) + | :node('member_declaration', ?( decl_specifiers ) ?( member_declarator_list ) ';' ) + | :node('typeless_function_declaration', constructor_declaration ';') + | using_declaration + | template_declaration + ; + +access_specifier = %'public protected private'; + +access_specification = :node( 'access_specification', access_specifier ':' ); + +member_error_recovery = :node( 'member_error', :cpp_block_error_recovery() ); + +member_specification = :node('member_specification', + +( access_specification + | member_declaration + | member_error_recovery ) ); + +class_key = %'class struct union'; + +base_class_name = :node( 'base_class_name', + ?('::') ?(nested_name_specifier) class_name ); + +base_specifier = :node( 'base_class_access', ?('virtual') ?( access_specifier ) ?('virtual') ) + base_class_name; + +# Notes: could use a subparser here: match ':' - '{' +base_clause = :node( 'class_bases', + ':' list( :node( 'base_specifier', base_specifier ), ',' ) ); + +class_head_name = :node( 'class_name', + optional_alternative( :node('dll_macro', id ), + ?( :node('nested_name_specifier', nested_name_specifier) ) + [:node('id', id) | template_id] ) ); + +class_head = class_key ?( class_head_name ) ?( base_clause ); + +class_specifier = :node( 'class_specifier', + class_head '{' ?( member_specification ) '}' ); + +# ############### A.8.2: Classes, Specials Member Functions ################## +# A.8.2, C++PL3 p.810 + +conversion_declarator = +( ptr_operator ); + +conversion_type_id = :node('conversion_type', + type_specifier ?( conversion_declarator )); + +conversion_function_id = :node('conversion_function_ref', + 'operator' conversion_type_id); + +mem_initializer_id = :node( 'mem_initializer_id', + [ ?('::') ?(nested_name_specifier) class_name ] + | id ); + +mem_initializer = :node( 'mem_initializer', + mem_initializer_id '(' ?( expression_list ) ')' ); + +ctor_initializer = :node( 'constructor_initializer', + ':' list( mem_initializer, ',' ) ); + +# ############### A.8.2: Classes, OverLoading ################## +# A.8.3, C++PL3 p.810 + +operator = %'+ - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> () []' + | [ %'new delete' ?( '[' ']' ) ]; + +operator_function_id = :node('operator_function_ref', + 'operator' operator ); + +# ############################## A.9: Templates ############################ +# A.9, C++PL3 p.811 + +template_name = id; + +template_argument = assignment_expression | type_id | template_name; + +template_argument_list = list( template_argument, ',' ); + +# don't you this until we can now for sure that the id of the template_name is really an id +# => would otherwise be confused with expression such as x < y && x > z. +template_id = :node( 'template_id', template_name '<' ?( template_argument_list ) '>' ); + +type_parameter = + :node('template_type_parameter', %'class typename' ?( id ) ?( '=' type_id ) ) + | :node('template_template_parameter', + 'template' '<' template_parameter_list '>' 'class' ?(id) + ?( '=' template_name ) ); + +template_parameter = type_parameter | :node('template_parameter', parameter_declaration ); + +template_parameter_list = :node('template_parameters', list( template_parameter, ',' ) ); + +template_declaration = :node( 'template_declaration', + 'template' '<' template_parameter_list '>' declaration ); + +explicit_instantiation = :node( 'explicit_template_instantiation', + 'template' declaration ); + +explicit_specialization = :node( 'explicit_template_specialization', + 'template' '<' '>' declaration ); + +# ############################## A.10: Exceptions ############################ +# A.10, C++PL3 p.812 + +throw_expression = 'throw' ?( assignment_expression ); + +exception_declaration = :node( 'exception_declaration', + [ type_specifier ?( declarator | abstract_declarator ) ] ) + | :node( 'ellipsis_exception_handler', '...' ); + +handler = :node('exception_handler', + 'catch' '(' exception_declaration ')' compound_statement ); + +handler_seq = +( handler ); + +type_id_list = :node( 'type_id_list', list( type_id, ',' ) ); +exception_specification = :node('exception_specification', + 'throw' '(' ?( type_id_list ) ')' ); + +try_block = :node( 'try_block', 'try' compound_statement handler_seq ); + +function_try_block = 'try' ?(ctor_initializer) function_body handler_seq; + Added: rfta/trunk/resources/prepro_algo.txt =================================================================== --- rfta/trunk/resources/prepro_algo.txt (rev 0) +++ rfta/trunk/resources/prepro_algo.txt 2007-04-11 06:10:34 UTC (rev 10) @@ -0,0 +1,13 @@ +Expand macro, then apply macro expansion on all identifiers of the result. +test3: ok +test2: don't expand first identifier of result if it the macro that was expanded. +test1: ok +test4: macro arguments are subsitued when calling another macro... + +Operation "x ## y" is used to concat left and right token into a single token. +A temporary string is build with the two tokens and must be lexed into a single token. +Arguments of ## operator must be defined in the macro replacement list. + +test8: ? what is rescanning ? +test9: macro parameter passed as string ? they may contains illegal token sequence: ": @\n". + Property changes on: rfta/trunk/src/lib_rftaparser ___________________________________________________________________ Name: svn:ignore + lexer.cpp This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rft...@li...> - 2007-04-10 22:21:43
|
Revision: 9 http://rfta.svn.sourceforge.net/rfta/?rev=9&view=rev Author: blep Date: 2007-04-10 15:21:42 -0700 (Tue, 10 Apr 2007) Log Message: ----------- - synchronized Added Paths: ----------- rfta/trunk/scons-LICENSE rfta/trunk/scons-README rfta/trunk/scons-time.py rfta/trunk/scons.py rfta/trunk/sconsign.py Copied: rfta/trunk/scons-LICENSE (from rev 5, rfta/vendor/scons/tags/0.96.95/scons-LICENSE) =================================================================== --- rfta/trunk/scons-LICENSE (rev 0) +++ rfta/trunk/scons-LICENSE 2007-04-10 22:21:42 UTC (rev 9) @@ -0,0 +1,25 @@ + Copyright and license for SCons - a software construction tool + + This copyright and license do not apply to any other software + with which this software may have been included. + +Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Copied: rfta/trunk/scons-README (from rev 5, rfta/vendor/scons/tags/0.96.95/scons-README) =================================================================== --- rfta/trunk/scons-README (rev 0) +++ rfta/trunk/scons-README 2007-04-10 22:21:42 UTC (rev 9) @@ -0,0 +1,204 @@ +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation + + SCons - a software construction tool + +This is the scons-README file for a version of SCons packaged for local +execution--that is, execution out of a specific local directory, without +having to install SCons as a system-wide utility. + +You are likely reading this file in one of the following two situations: + + 1) You have unpacked an scons-local-{version} package and are + examining the contents. + + In this case, you are presumably interested in using this + package to include a local copy of SCons with some other + software that you package, so that you can use SCons to build + your software without forcing all of your users to have it fully + installed. Instructions for this can be found below. + + If you are not looking to use SCons in this way, then please + use either the scons-{version} package to install SCons on your + system, or the scons-src-{version} package if you want the full + source to SCons, including its packaging code and underlying + tests and testing infrastructure. + + 2) This file was included in some other software package so that + the package could be built using SCons. + + In this case, follow the instructions provided with the + rest of the software package for how to use SCons to build + and/or install the software. The file containing build and + installation instructions will typically be named README or + INSTALL. + +LATEST VERSION +============== + +Before going further, you can check for the latest version of the +scons-local package, or any SCons package, at the SCons download page: + + http://www.scons.org/download.html + + +EXECUTION REQUIREMENTS +====================== + +Running SCons requires Python version 1.5.2 or later. There should be +no other dependencies or requirements to run SCons. + +The default SCons configuration assumes use of the Microsoft Visual C++ +compiler suite on WIN32 systems, and assumes a C compiler named 'cc', +a C++ compiler named 'c++', and a Fortran compiler named 'g77' (such +as found in the GNU C compiler suite) on any other type of system. +You may, of course, override these default values by appropriate +configuration of Environment construction variables. + + +INSTALLATION +============ + +Installation of this package should be as simple as unpacking the +archive (either .tar.gz or .zip) in any directory (top-level or a +subdirectory) within the software package with which you want to ship +SCons. + +Once you have installed this package, you should write an SConstruct +file at the top level of your source tree to build your software as you +see fit. + +Then modify the build/install instructions for your package to instruct +your users to execute SCons as follows (if you installed this package in +your top-level directory): + + $ python scons.py + +Or (if, for example, you installed this package in a subdirectory named +"scons"): + + $ python scons/scons.py + +That should be all you have to do. (If it isn't that simple, please let +us know!) + + +CONTENTS OF THIS PACKAGE +======================== + +This scons-local package consists of the following: + +scons-LICENSE + A copy of the copyright and terms under which SCons is + distributed (the Open Source Initiative-approved MIT license). + + A disclaimer has been added to the beginning to make clear that + this license applies only to SCons, and not to any separate + software you've written with which you're planning to package + SCons. + +scons-README + What you're looking at right now. + +scons-local-{version}/ + The SCons build engine. This is structured as a Python + library. + +scons.py + The SCons script itself. The script sets up the Python + sys.path variable to use the build engine found in the + scons-local-{version}/ directory in preference to any other + SCons build engine installed on your system. + + +DOCUMENTATION +============= + +Because this package is intended to be included with other software by +experienced users, we have not included any SCons documentation in this +package (other than this scons-README file you're reading right now). + +If, however, you need documentation about SCons, then consult any of the +following from the corresponding scons-{version} or scons-src-{version} +package: + + The RELEASE.txt file (src/RELEASE.txt file in the + scons-src-{version} package), which contains notes about this + specific release, including known problems. + + The CHANGES.txt file (src/CHANGES.txt file in the + scons-src-{version} package), which contains a list of changes + since the previous release. + + The scons.1 man page (doc/man/scons.1 in the scons-src-{version} + package), which contains a section of small examples for getting + started using SCons. + +Additional documentation for SCons is available at: + + http://www.scons.org/doc.html + + +LICENSING +========= + +SCons is distributed under the MIT license, a full copy of which is +available in the scons-LICENSE file in this package. The MIT license is +an approved Open Source license, which means: + + This software is OSI Certified Open Source Software. OSI + Certified is a certification mark of the Open Source Initiative. + +More information about OSI certifications and Open Source software is +available at: + + http://www.opensource.org/ + + +REPORTING BUGS +============== + +You can report bugs either by following the "Tracker - Bugs" link +on the SCons project page: + + http://sourceforge.net/projects/scons/ + +or by sending mail to the SCons developers mailing list: + + sco...@li... + + +MAILING LISTS +============= + +A mailing list for users of SCons is available. You may send questions +or comments to the list at: + + sco...@li... + +You may subscribe to the scons-users mailing list at: + + http://lists.sourceforge.net/lists/listinfo/scons-users + + +FOR MORE INFORMATION +==================== + +Check the SCons web site at: + + http://www.scons.org/ + + +AUTHOR INFO +=========== + +Steven Knight +knight at baldmt dot com +http://www.baldmt.com/~knight/ + +With plenty of help from the SCons Development team: + Chad Austin + Charles Crain + Steve Leblanc + Anthony Roach + Terrel Shumway + Copied: rfta/trunk/scons-time.py (from rev 5, rfta/vendor/scons/tags/0.96.95/scons-time.py) =================================================================== --- rfta/trunk/scons-time.py (rev 0) +++ rfta/trunk/scons-time.py 2007-04-10 22:21:42 UTC (rev 9) @@ -0,0 +1,1439 @@ +#!/usr/bin/env python +# +# scons-time - run SCons timings and collect statistics +# +# A script for running a configuration through SCons with a standard +# set of invocations to collect timing and memory statistics and to +# capture the results in a consistent set of output files for display +# and analysis. +# + +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/script/scons-time.py 0.96.95.D001 2007/02/12 21:41:50 knight" + +import getopt +import glob +import os +import re +import shutil +import string +import sys +import tempfile +import time + +class Plotter: + def increment_size(self, largest): + """ + Return the size of each horizontal increment line for a specified + maximum value. This returns a value that will provide somewhere + between 5 and 9 horizontal lines on the graph, on some set of + boundaries that are multiples of 10/100/1000/etc. + """ + i = largest / 5 + if not i: + return largest + multiplier = 1 + while i >= 10: + i = i / 10 + multiplier = multiplier * 10 + return i * multiplier + + def max_graph_value(self, largest): + # Round up to next integer. + largest = int(largest) + 1 + increment = self.increment_size(largest) + return ((largest + increment - 1) / increment) * increment + +class Line: + def __init__(self, points, type, title, label, comment, fmt="%s %s"): + self.points = points + self.type = type + self.title = title + self.label = label + self.comment = comment + self.fmt = fmt + + def print_label(self, inx, x, y): + if self.label: + print 'set label %s "%s" at %s,%s right' % (inx, self.label, x, y) + + def plot_string(self): + if self.title: + title_string = 'title "%s"' % self.title + else: + title_string = 'notitle' + return "'-' %s with lines lt %s" % (title_string, self.type) + + def print_points(self, fmt=None): + if fmt is None: + fmt = self.fmt + if self.comment: + print '# %s' % self.comment + for x, y in self.points: + print fmt % (x, y) + print 'e' + + def get_x_values(self): + return [ p[0] for p in self.points ] + + def get_y_values(self): + return [ p[1] for p in self.points ] + +class Gnuplotter(Plotter): + + def __init__(self, title, key_location): + self.lines = [] + self.title = title + self.key_location = key_location + + def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'): + if points: + line = Line(points, type, title, label, comment, fmt) + self.lines.append(line) + + def plot_string(self, line): + return line.plot_string() + + def vertical_bar(self, x, type, label, comment): + if self.get_min_x() <= x and x <= self.get_max_x(): + points = [(x, 0), (x, self.get_max_x())] + self.line(points, type, label, comment) + + def get_all_x_values(self): + result = [] + for line in self.lines: + result.extend(line.get_x_values()) + return result + + def get_all_y_values(self): + result = [] + for line in self.lines: + result.extend(line.get_y_values()) + return result + + def get_min_x(self): + try: + return self.min_x + except AttributeError: + self.min_x = min(self.get_all_x_values()) + return self.min_x + + def get_max_x(self): + try: + return self.max_x + except AttributeError: + self.max_x = max(self.get_all_x_values()) + return self.max_x + + def get_min_y(self): + try: + return self.min_y + except AttributeError: + self.min_y = min(self.get_all_y_values()) + return self.min_y + + def get_max_y(self): + try: + return self.max_y + except AttributeError: + self.max_y = max(self.get_all_y_values()) + return self.max_y + + def draw(self): + + if not self.lines: + return + + if self.title: + print 'set title "%s"' % self.title + print 'set key %s' % self.key_location + + inx = 1 + max_y = self.max_graph_value(self.get_max_y())/2 + for line in self.lines: + line.print_label(inx, line.points[0][0]-1, max_y) + inx += 1 + + plot_strings = [ self.plot_string(l) for l in self.lines ] + print 'plot ' + ', \\\n '.join(plot_strings) + + for line in self.lines: + line.print_points() + + + +def untar(fname): + import tarfile + tar = tarfile.open(name=fname, mode='r') + for tarinfo in tar: + tar.extract(tarinfo) + tar.close() + +def unzip(fname): + import zipfile + zf = zipfile.ZipFile(fname, 'r') + for name in zf.namelist(): + dir = os.path.dirname(name) + try: + os.makedirs(dir) + except: + pass + open(name, 'w').write(zf.read(name)) + +def read_tree(dir): + def read_files(arg, dirname, fnames): + for fn in fnames: + fn = os.path.join(dirname, fn) + if os.path.isfile(fn): + open(fn, 'rb').read() + os.path.walk('.', read_files, None) + +def redirect_to_file(command, log): + return '%s > %s 2>&1' % (command, log) + +def tee_to_file(command, log): + return '%s 2>&1 | tee %s' % (command, log) + + + +class SConsTimer: + """ + Usage: scons-time SUBCOMMAND [ARGUMENTS] + Type "scons-time help SUBCOMMAND" for help on a specific subcommand. + + Available subcommands: + func Extract test-run data for a function + help Provides help + mem Extract --debug=memory data from test runs + obj Extract --debug=count data from test runs + time Extract --debug=time data from test runs + run Runs a test configuration + """ + + name = 'scons-time' + name_spaces = ' '*len(name) + + def makedict(**kw): + return kw + + default_settings = makedict( + aegis = 'aegis', + aegis_project = None, + chdir = None, + config_file = None, + initial_commands = [], + key_location = 'bottom left', + orig_cwd = os.getcwd(), + outdir = None, + prefix = '', + python = '"%s"' % sys.executable, + redirect = redirect_to_file, + scons = None, + scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', + scons_lib_dir = None, + scons_wrapper = None, + startup_targets = '--help', + subdir = None, + subversion_url = None, + svn = 'svn', + svn_co_flag = '-q', + tar = 'tar', + targets = '', + targets0 = None, + targets1 = None, + targets2 = None, + title = None, + unzip = 'unzip', + verbose = False, + vertical_bars = [], + + unpack_map = { + '.tar.gz' : (untar, '%(tar)s xzf %%s'), + '.tgz' : (untar, '%(tar)s xzf %%s'), + '.tar' : (untar, '%(tar)s xf %%s'), + '.zip' : (unzip, '%(unzip)s %%s'), + }, + ) + + run_titles = [ + 'Startup', + 'Full build', + 'Up-to-date build', + ] + + run_commands = [ + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s', + ] + + stages = [ + 'pre-read', + 'post-read', + 'pre-build', + 'post-build', + ] + + stage_strings = { + 'pre-read' : 'Memory before reading SConscript files:', + 'post-read' : 'Memory after reading SConscript files:', + 'pre-build' : 'Memory before building targets:', + 'post-build' : 'Memory after building targets:', + } + + memory_string_all = 'Memory ' + + default_stage = stages[-1] + + time_strings = { + 'total' : 'Total build time', + 'SConscripts' : 'Total SConscript file execution time', + 'SCons' : 'Total SCons execution time', + 'commands' : 'Total command execution time', + } + + time_string_all = 'Total .* time' + + # + + def __init__(self): + self.__dict__.update(self.default_settings) + + # Functions for displaying and executing commands. + + def subst(self, x, dictionary): + try: + return x % dictionary + except TypeError: + # x isn't a string (it's probably a Python function), + # so just return it. + return x + + def subst_variables(self, command, dictionary): + """ + Substitutes (via the format operator) the values in the specified + dictionary into the specified command. + + The command can be an (action, string) tuple. In all cases, we + perform substitution on strings and don't worry if something isn't + a string. (It's probably a Python function to be executed.) + """ + try: + command + '' + except TypeError: + action = command[0] + string = command[1] + args = command[2:] + else: + action = command + string = action + args = (()) + action = self.subst(action, dictionary) + string = self.subst(string, dictionary) + return (action, string, args) + + def _do_not_display(self, msg, *args): + pass + + def display(self, msg, *args): + """ + Displays the specified message. + + Each message is prepended with a standard prefix of our name + plus the time. + """ + if callable(msg): + msg = msg(*args) + else: + msg = msg % args + if msg is None: + return + fmt = '%s[%s]: %s\n' + sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg)) + + def _do_not_execute(self, action, *args): + pass + + def execute(self, action, *args): + """ + Executes the specified action. + + The action is called if it's a callable Python function, and + otherwise passed to os.system(). + """ + if callable(action): + action(*args) + else: + os.system(action % args) + + def run_command_list(self, commands, dict): + """ + Executes a list of commands, substituting values from the + specified dictionary. + """ + commands = [ self.subst_variables(c, dict) for c in commands ] + for action, string, args in commands: + self.display(string, *args) + sys.stdout.flush() + status = self.execute(action, *args) + if status: + sys.exit(status) + + def log_display(self, command, log): + command = self.subst(command, self.__dict__) + if log: + command = self.redirect(command, log) + return command + + def log_execute(self, command, log): + command = self.subst(command, self.__dict__) + output = os.popen(command).read() + if self.verbose: + sys.stdout.write(output) + open(log, 'wb').write(output) + + # + + def archive_splitext(self, path): + """ + Splits an archive name into a filename base and extension. + + This is like os.path.splitext() (which it calls) except that it + also looks for '.tar.gz' and treats it as an atomic extensions. + """ + if path.endswith('.tar.gz'): + return path[:-7], path[-7:] + else: + return os.path.splitext(path) + + def args_to_files(self, args, tail=None): + """ + Takes a list of arguments, expands any glob patterns, and + returns the last "tail" files from the list. + """ + files = [] + for a in args: + g = glob.glob(a) + g.sort() + files.extend(g) + + if tail: + files = files[-tail:] + + return files + + def ascii_table(self, files, columns, + line_function, file_function=lambda x: x, + *args, **kw): + + header_fmt = ' '.join(['%12s'] * len(columns)) + line_fmt = header_fmt + ' %s' + + print header_fmt % columns + + for file in files: + t = line_function(file, *args, **kw) + diff = len(columns) - len(t) + if diff > 0: + t += [''] * diff + t.append(file_function(file)) + print line_fmt % tuple(t) + + def collect_results(self, files, function, *args, **kw): + results = {} + + for file in files: + base = os.path.splitext(file)[0] + run, index = string.split(base, '-')[-2:] + + run = int(run) + index = int(index) + + value = function(file, *args, **kw) + + try: + r = results[index] + except KeyError: + r = [] + results[index] = r + r.append((run, value)) + + return results + + def doc_to_help(self, obj): + """ + Translates an object's __doc__ string into help text. + + This strips a consistent number of spaces from each line in the + help text, essentially "outdenting" the text to the left-most + column. + """ + doc = obj.__doc__ + if doc is None: + return '' + return self.outdent(doc) + + def find_next_run_number(self, dir, prefix): + """ + Returns the next run number in a directory for the specified prefix. + + Examines the contents the specified directory for files with the + specified prefix, extracts the run numbers from each file name, + and returns the next run number after the largest it finds. + """ + x = re.compile(re.escape(prefix) + '-([0-9]+).*') + matches = map(lambda e, x=x: x.match(e), os.listdir(dir)) + matches = filter(None, matches) + if not matches: + return 0 + run_numbers = map(lambda m: int(m.group(1)), matches) + return int(max(run_numbers)) + 1 + + def gnuplot_results(self, results, fmt='%s %.3f'): + """ + Prints out a set of results in Gnuplot format. + """ + gp = Gnuplotter(self.title, self.key_location) + + indices = results.keys() + indices.sort() + + for i in indices: + try: + t = self.run_titles[i] + except IndexError: + t = '??? %s ???' % i + results[i].sort() + gp.line(results[i], i+1, t, None, t, fmt=fmt) + + for bar_tuple in self.vertical_bars: + try: + x, type, label, comment = bar_tuple + except ValueError: + x, type, label = bar_tuple + comment = label + gp.vertical_bar(x, type, None, label, comment) + + gp.draw() + + def logfile_name(self, invocation): + """ + Returns the absolute path of a log file for the specificed + invocation number. + """ + name = self.prefix_run + '-%d.log' % invocation + return os.path.join(self.outdir, name) + + def outdent(self, s): + """ + Strip as many spaces from each line as are found at the beginning + of the first line in the list. + """ + lines = s.split('\n') + if lines[0] == '': + lines = lines[1:] + spaces = re.match(' *', lines[0]).group(0) + def strip_initial_spaces(l, s=spaces): + if l.startswith(spaces): + l = l[len(spaces):] + return l + return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' + + def profile_name(self, invocation): + """ + Returns the absolute path of a profile file for the specified + invocation number. + """ + name = self.prefix_run + '-%d.prof' % invocation + return os.path.join(self.outdir, name) + + def set_env(self, key, value): + os.environ[key] = value + + # + + def get_debug_times(self, file, time_string=None): + """ + Fetch times from the --debug=time strings in the specified file. + """ + if time_string is None: + search_string = self.time_string_all + else: + search_string = time_string + contents = open(file).read() + result = re.findall(r'%s: ([\d\.]*)' % search_string, contents)[-4:] + result = [ float(r) for r in result ] + if not time_string is None: + result = result[0] + return result + + def get_function_profile(self, file, function): + """ + Returns the file, line number, function name, and cumulative time. + """ + try: + import pstats + except ImportError, e: + sys.stderr.write('%s: func: %s\n' % (self.name, e)) + sys.stderr.write('%s This version of Python is missing the profiler.\n' % self.name_spaces) + sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) + sys.exit(1) + statistics = pstats.Stats(file).stats + matches = [ e for e in statistics.items() if e[0][2] == function ] + r = matches[0] + return r[0][0], r[0][1], r[0][2], r[1][3] + + def get_function_time(self, file, function): + """ + Returns just the cumulative time for the specified function. + """ + return self.get_function_profile(file, function)[3] + + def get_memory(self, file, memory_string=None): + """ + Returns a list of integers of the amount of memory used. The + default behavior is to return all the stages. + """ + if memory_string is None: + search_string = self.memory_string_all + else: + search_string = memory_string + lines = open(file).readlines() + lines = [ l for l in lines if l.startswith(search_string) ][-4:] + result = [ int(l.split()[-1]) for l in lines[-4:] ] + if len(result) == 1: + result = result[0] + return result + + def get_object_counts(self, file, object_name, index=None): + """ + Returns the counts of the specified object_name. + """ + object_string = ' ' + object_name + '\n' + lines = open(file).readlines() + line = [ l for l in lines if l.endswith(object_string) ][0] + result = [ int(field) for field in line.split()[:4] ] + if not index is None: + result = result[index] + return result + + # + + command_alias = {} + + def execute_subcommand(self, argv): + """ + Executes the do_*() function for the specified subcommand (argv[0]). + """ + if not argv: + return + cmdName = self.command_alias.get(argv[0], argv[0]) + try: + func = getattr(self, 'do_' + cmdName) + except AttributeError: + return self.default(argv) + try: + return func(argv) + except TypeError, e: + sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e)) + import traceback + traceback.print_exc(file=sys.stderr) + sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName)) + + def default(self, argv): + """ + The default behavior for an unknown subcommand. Prints an + error message and exits. + """ + sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0])) + sys.stderr.write('Type "%s help" for usage.\n' % self.name) + sys.exit(1) + + # + + def do_help(self, argv): + """ + """ + if argv[1:]: + for arg in argv[1:]: + try: + func = getattr(self, 'do_' + arg) + except AttributeError: + sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg)) + else: + try: + help = getattr(self, 'help_' + arg) + except AttributeError: + sys.stdout.write(self.doc_to_help(func)) + sys.stdout.flush() + else: + help() + else: + doc = self.doc_to_help(self.__class__) + if doc: + sys.stdout.write(doc) + sys.stdout.flush() + return None + + # + + def help_func(self): + help = """\ + Usage: scons-time func [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + --func=NAME, --function=NAME Report time for function NAME + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_func(self, argv): + """ + """ + format = 'ascii' + function_name = '_main' + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'func=', + 'function=', + 'help', + 'prefix=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('--func', '--function'): + function_name = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'func']) + sys.exit(0) + elif o in ('--max'): + max_time = int(a) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title'): + self.title = a + + if self.config_file: + execfile(self.config_file, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + + if not args: + + pattern = '%s*.prof' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: func: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help func" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + def print_function_timing(file, func): + try: + f, line, func, time = self.get_function_profile(file, func) + except ValueError, e: + sys.stderr.write("%s: func: %s: %s\n" % (self.name, file, e)) + else: + if f.startswith(cwd_): + f = f[len(cwd_):] + print "%.3f %s:%d(%s)" % (time, f, line, func) + + for file in args: + print_function_timing(file, function_name) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_function_time, + function_name) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + # + + def help_mem(self): + help = """\ + Usage: scons-time mem [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_mem(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'mem']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage'): + if not a in self.stages: + sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title'): + self.title = a + + if self.config_file: + execfile(self.config_file, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x, c=self.chdir: os.path.join(c, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: mem: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help mem" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_memory, + self.stage_strings[stage]) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_obj(self): + help = """\ + Usage: scons-time obj [OPTIONS] OBJECT FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_obj(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'obj']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage'): + if not a in self.stages: + sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title'): + self.title = a + + if not args: + sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + object_name = args.pop(0) + + if self.config_file: + execfile(self.config_file, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x, c=self.chdir: os.path.join(c, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: obj: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name) + + elif format == 'gnuplot': + + stage_index = 0 + for s in self.stages: + if stage == s: + break + stage_index = stage_index + 1 + + results = self.collect_results(args, self.get_object_counts, + object_name, stage_index) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_run(self): + help = """\ + Usage: scons-time run [OPTIONS] [FILE ...] + + --aegis=PROJECT Use SCons from the Aegis PROJECT + --chdir=DIR Name of unpacked directory for chdir + -f FILE, --file=FILE Read configuration from specified FILE + -h, --help Print this help and exit + -n, --no-exec No execute, just print command lines + --number=NUMBER Put output in files for run NUMBER + --outdir=OUTDIR Put output files in OUTDIR + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --python=PYTHON Time using the specified PYTHON + -q, --quiet Don't print command lines + --scons=SCONS Time using the specified SCONS + --svn=URL, --subversion=URL Use SCons from Subversion URL + -v, --verbose Display output of commands + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_run(self, argv): + """ + """ + run_number_list = [None] + + short_opts = '?f:hnp:qs:v' + + long_opts = [ + 'aegis=', + 'file=', + 'help', + 'no-exec', + 'number=', + 'outdir=', + 'prefix=', + 'python=', + 'quiet', + 'scons=', + 'svn=', + 'subdir=', + 'subversion=', + 'verbose', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('--aegis'): + self.aegis_project = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'run']) + sys.exit(0) + elif o in ('-n', '--no-exec'): + self.execute = self._do_not_execute + elif o in ('--number'): + run_number_list = self.split_run_numbers(a) + elif o in ('--outdir'): + self.outdir = a + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--python'): + self.python = a + elif o in ('-q', '--quiet'): + self.display = self._do_not_display + elif o in ('-s', '--subdir'): + self.subdir = a + elif o in ('--scons'): + self.scons = a + elif o in ('--svn', '--subversion'): + self.subversion_url = a + elif o in ('-v', '--verbose'): + self.redirect = tee_to_file + self.verbose = True + self.svn_co_flag = '' + + if not args and not self.config_file: + sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name) + sys.stderr.write('%s Type "%s help run" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + if self.config_file: + execfile(self.config_file, self.__dict__) + + if args: + self.archive_list = args + + archive_file_name = os.path.split(self.archive_list[0])[1] + + if not self.subdir: + self.subdir = self.archive_splitext(archive_file_name)[0] + + if not self.prefix: + self.prefix = self.archive_splitext(archive_file_name)[0] + + prepare = None + if self.subversion_url: + prepare = self.prep_subversion_run + elif self.aegis_project: + prepare = self.prep_aegis_run + + for run_number in run_number_list: + self.individual_run(run_number, self.archive_list, prepare) + + def split_run_numbers(self, s): + result = [] + for n in s.split(','): + try: + x, y = n.split('-') + except ValueError: + result.append(int(n)) + else: + result.extend(range(int(x), int(y)+1)) + return result + + def scons_path(self, dir): + return os.path.join(dir, 'src', 'script', 'scons.py') + + def scons_lib_dir_path(self, dir): + return os.path.join(dir, 'src', 'engine') + + def prep_aegis_run(self, commands, removals): + self.aegis_tmpdir = tempfile.mktemp(prefix = self.name + '-aegis-') + removals.append((shutil.rmtree, 'rm -rf %%s', self.aegis_tmpdir)) + + self.aegis_parent_project = os.path.splitext(self.aegis_project)[0] + self.scons = self.scons_path(self.aegis_tmpdir) + self.scons_lib_dir = self.scons_lib_dir_path(self.aegis_tmpdir) + + commands.extend([ + 'mkdir %(aegis_tmpdir)s', + (lambda: os.chdir(self.aegis_tmpdir), 'cd %(aegis_tmpdir)s'), + '%(aegis)s -cp -ind -p %(aegis_parent_project)s .', + '%(aegis)s -cp -ind -p %(aegis_project)s -delta %(run_number)s .', + ]) + + def prep_subversion_run(self, commands, removals): + self.svn_tmpdir = tempfile.mktemp(prefix = self.name + '-svn-') + removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir)) + + self.scons = self.scons_path(self.svn_tmpdir) + self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir) + + commands.extend([ + 'mkdir %(svn_tmpdir)s', + '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s', + ]) + + def individual_run(self, run_number, archive_list, prepare=None): + """ + Performs an individual run of the default SCons invocations. + """ + + commands = [] + removals = [] + + if prepare: + prepare(commands, removals) + + save_scons = self.scons + save_scons_wrapper = self.scons_wrapper + save_scons_lib_dir = self.scons_lib_dir + + if self.outdir is None: + self.outdir = self.orig_cwd + elif not os.path.isabs(self.outdir): + self.outdir = os.path.join(self.orig_cwd, self.outdir) + + if self.scons is None: + self.scons = self.scons_path(self.orig_cwd) + + if self.scons_lib_dir is None: + self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd) + + if self.scons_wrapper is None: + self.scons_wrapper = self.scons + + if not run_number: + run_number = self.find_next_run_number(self.outdir, self.prefix) + + self.run_number = str(run_number) + + self.prefix_run = self.prefix + '-%03d' % run_number + + if self.targets0 is None: + self.targets0 = self.startup_targets + if self.targets1 is None: + self.targets1 = self.targets + if self.targets2 is None: + self.targets2 = self.targets + + self.tmpdir = tempfile.mktemp(prefix = self.name + '-') + + commands.extend([ + 'mkdir %(tmpdir)s', + + (os.chdir, 'cd %%s', self.tmpdir), + ]) + + for archive in archive_list: + if not os.path.isabs(archive): + archive = os.path.join(self.orig_cwd, archive) + if os.path.isdir(archive): + dest = os.path.split(archive)[1] + commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest)) + else: + suffix = self.archive_splitext(archive)[1] + commands.append(self.unpack_map[suffix] + (archive,)) + + commands.extend([ + (os.chdir, 'cd %%s', self.subdir), + ]) + + commands.extend(self.initial_commands) + + commands.extend([ + (lambda: read_tree('.'), + 'find * -type f | xargs cat > /dev/null'), + + (self.set_env, 'export %%s=%%s', + 'SCONS_LIB_DIR', self.scons_lib_dir), + + '%(python)s %(scons_wrapper)s --version', + ]) + + index = 0 + for run_command in self.run_commands: + setattr(self, 'prof%d' % index, self.profile_name(index)) + c = ( + self.log_execute, + self.log_display, + run_command, + self.logfile_name(index), + ) + commands.append(c) + index = index + 1 + + commands.extend([ + (os.chdir, 'cd %%s', self.orig_cwd), + ]) + + if not os.environ.get('PRESERVE'): + commands.extend(removals) + + commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir)) + + self.run_command_list(commands, self.__dict__) + + self.scons = save_scons + self.scons_lib_dir = save_scons_lib_dir + self.scons_wrapper = save_scons_wrapper + + # + + def help_time(self): + help = """\ + Usage: scons-time time [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --which=TIMER Plot timings for TIMER: total, + SConscripts, SCons, commands. + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_time(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + tail = None + which = 'total' + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'tail=', + 'title=', + 'which=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'time']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title'): + self.title = a + elif o in ('--which'): + if not a in self.time_strings.keys(): + sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + which = a + + if self.config_file: + execfile(self.config_file, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x, c=self.chdir: os.path.join(c, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: time: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + columns = ("Total", "SConscripts", "SCons", "commands") + self.ascii_table(args, columns, self.get_debug_times, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_debug_times, + self.time_strings[which]) + + self.gnuplot_results(results, fmt='%s %.6f') + + else: + + sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + +if __name__ == '__main__': + opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) + + ST = SConsTimer() + + for o, a in opts: + if o in ('-?', '-h', '--help'): + ST.do_help(['help']) + sys.exit(0) + elif o in ('-V', '--version'): + sys.stdout.write('scons-time version\n') + sys.exit(0) + + if not args: + sys.stderr.write('Type "%s help" for usage.\n' % ST.name) + sys.exit(1) + + ST.execute_subcommand(args) Copied: rfta/trunk/scons.py (from rev 5, rfta/vendor/scons/tags/0.96.95/scons.py) =================================================================== --- rfta/trunk/scons.py (rev 0) +++ rfta/trunk/scons.py 2007-04-10 22:21:42 UTC (rev 9) @@ -0,0 +1,161 @@ +#! /usr/bin/env python +# +# SCons - a Software Constructor +# +# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "/home/scons/scons/branch.0/branch.96/baseline/src/script/scons.py 0.96.95.D002 2007/02/14 11:01:59 knight" + +__version__ = "0.96.95" + +__build__ = "D002" + +__buildsys__ = "roxbury" + +__date__ = "2007/02/14 11:01:59" + +__developer__ = "knight" + +import os +import os.path +import sys + +############################################################################## +# BEGIN STANDARD SCons SCRIPT HEADER +# +# This is the cut-and-paste logic so that a self-contained script can +# interoperate correctly with different SCons versions and installation +# locations for the engine. If you modify anything in this section, you +# should also change other scripts that use this same header. +############################################################################## + +# Strip the script directory from sys.path() so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. Replace it with our own library directories +# (version-specific first, in case they installed by hand there, +# followed by generic) so we pick up the right version of the build +# engine modules if they're in either directory. + +script_dir = sys.path[0] + +if script_dir in sys.path: + sys.path.remove(script_dir) + +libs = [] + +if os.environ.has_key("SCONS_LIB_DIR"): + libs.append(os.environ["SCONS_LIB_DIR"]) + +local = 'scons-local-' + __version__ +if script_dir: + local = os.path.join(script_dir, local) +libs.append(os.path.abspath(local)) + +scons_version = 'scons-%s' % __version__ + +prefs = [] + +if sys.platform == 'win32': + # sys.prefix is (likely) C:\Python*; + # check only C:\Python*. + prefs.append(sys.prefix) + prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages')) +else: + # On other (POSIX) platforms, things are more complicated due to + # the variety of path names and library locations. Try to be smart + # about it. + if script_dir == 'bin': + # script_dir is `pwd`/bin; + # check `pwd`/lib/scons*. + prefs.append(os.getcwd()) + else: + if script_dir == '.' or script_dir == '': + script_dir = os.getcwd() + head, tail = os.path.split(script_dir) + ... [truncated message content] |
From: <rft...@li...> - 2007-04-10 22:19:27
|
Revision: 8 http://rfta.svn.sourceforge.net/rfta/?rev=8&view=rev Author: blep Date: 2007-04-10 15:19:26 -0700 (Tue, 10 Apr 2007) Log Message: ----------- - synchronized Added Paths: ----------- rfta/trunk/scons-local-0.96.95/ Copied: rfta/trunk/scons-local-0.96.95 (from rev 7, rfta/vendor/scons/tags/0.96.95/scons-local-0.96.95) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |