Update of /cvsroot/cpptool/rfta/src/rftaparser In directory sc8-pr-cvs1:/tmp/cvs-serv25838/src/rftaparser Added Files: UnparsedDeclarationMutatorTest.h UnparsedDeclarationMutatorTest.cpp UnparsedDeclarationMutator.h UnparsedDeclarationMutator.cpp Log Message: -- declaration parsing (splits to specifier and declarators) -- this is different to variabledeclmutator ! --- NEW FILE: UnparsedDeclarationMutatorTest.h --- // ////////////////////////////////////////////////////////////////////////// // Header file UnparsedDeclarationMutatorTest.h for class UnparsedDeclarationMutatorTest // (c)Copyright 2003, Andre Baresel. // Created: 2003/04/18 // ////////////////////////////////////////////////////////////////////////// #ifndef RFTA_UnparsedDeclarationMutatorTest_H #define RFTA_UnparsedDeclarationMutatorTest_H #include "ParserTesting.h" namespace Refactoring { /// Unit tests for UnparsedDeclarationMutatorTest class UnparsedDeclarationMutatorTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( UnparsedDeclarationMutatorTest ); CPPUNIT_TEST( testSimpleDeclaration ); //CPPUNIT_TEST( testSpecialNestedName ); // will fail because type information is needed CPPUNIT_TEST( testFunctionDeclaration ); CPPUNIT_TEST( testClassDeclaration ); CPPUNIT_TEST( testClassDeclarationWithInheritance ); CPPUNIT_TEST( testEnumDeclaration ); CPPUNIT_TEST( testPointerDecl ); CPPUNIT_TEST( testFctPointer ); CPPUNIT_TEST( testUserTypeFctPointer ); CPPUNIT_TEST( testSimpleTemplate ); CPPUNIT_TEST( testParameterTemplate ); CPPUNIT_TEST( testElaboratedClass ); CPPUNIT_TEST( testElaboratedUnion ); CPPUNIT_TEST( testUnnamedStruct ); CPPUNIT_TEST( testDeclareOperator ); // will fail because of a 'todo' CPPUNIT_TEST( testConvertOperator ); // will fail because of a 'todo' CPPUNIT_TEST( testDetectFunctionPtr ); CPPUNIT_TEST( testDetectUserDefType_Ptr ); CPPUNIT_TEST( testDetectUserDefType_Ref ); CPPUNIT_TEST( testDeclaringConst ); CPPUNIT_TEST( testDeclaringExceptions ); CPPUNIT_TEST( testDeclaringArray ); CPPUNIT_TEST( testStructTypedef ); CPPUNIT_TEST( testTypedefDeclaration ); CPPUNIT_TEST_SUITE_END(); public: /*! Constructs a UnparsedDeclarationMutatorTest object. */ UnparsedDeclarationMutatorTest(); /// Destructor. virtual ~UnparsedDeclarationMutatorTest(); void setUp(); void tearDown(); void testSimpleDeclaration(); void testFunctionDeclaration(); void testClassDeclaration(); void testClassDeclarationWithInheritance(); void testEnumDeclaration(); void testPointerDecl(); void testFctPointer(); void testUserTypeFctPointer(); void testSimpleTemplate(); void testParameterTemplate(); void testSpecialNestedName(); void testElaboratedClass(); void testElaboratedUnion(); void testUnnamedStruct(); void testDeclareOperator(); void testConvertOperator(); void testDetectFunctionPtr(); void testDetectUserDefType_Ptr(); void testDetectUserDefType_Ref(); void testDeclaringConst(); void testDeclaringExceptions(); void testDeclaringArray(); void testStructTypedef(); void testTypedefDeclaration(); private: /// Prevents the use of the copy constructor. UnparsedDeclarationMutatorTest( const UnparsedDeclarationMutatorTest &other ); /// Prevents the use of the copy operator. void operator =( const UnparsedDeclarationMutatorTest &other ); private: }; // Inlines methods for UnparsedDeclarationMutatorTest: // ------------------------------------------------ } // namespace Refactoring #endif // RFTA_UnparsedDeclarationMutatorTest_H --- NEW FILE: UnparsedDeclarationMutatorTest.cpp --- // ////////////////////////////////////////////////////////////////////////// // Implementation file UnparsedDeclarationMutatorTest.cpp for class UnparsedDeclarationMutatorTest // (c)Copyright 2003, Andre Baresel. // Created: 2003/04/18 // ////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "UnparsedDeclarationMutator.h" #include "UnparsedDeclarationMutatorTest.h" #include <rfta/parser/ASTNode.h> #include <rfta/parser/ASTNodes.h> #include <rfta/parser/ParseContext.h> #include <rfta/parser/SourceASTNode.h> #include <boost/format.hpp> namespace Refactoring { RFTAPARSER_TEST_SUITE_REGISTRATION( UnparsedDeclarationMutatorTest ); namespace Testing { static SourceASTNodePtr checkDeclarationMutatorPass( const std::string &source, const CppUnit::SourceLine &sourceLine ) { SourceASTNodePtr sourceNode = SourceASTNode::create( source, source ); ParseContext context( sourceNode ); // simulate statement level parsing ASTNodePtr statement = ASTNode::create( ASTNodeTypes::declarationOrExpression, sourceNode, 0, source.length(), sourceNode ); context.addNode( statement ); // do variable declaration parsing UnparsedDeclarationMutator mutator( context, statement, sourceNode ); CppUnit::Message message( "mutator failed", "Source:\n" + source ); CppUnit::Asserter::failIf( !mutator.tryMutate(), message, sourceLine ); return sourceNode; } static void checkDeclaration( const std::string& source, const SourceASTNodePtr& sourceNode, const std::vector<int> specifierStart, const std::vector<int> specifierLen, const std::vector<int> declStart, const std::vector<int> declLen, const CppUnit::SourceLine &sourceLine ) { ASTNodePtr node = sourceNode->getChildAt(0); int specifierCount = __min(specifierStart.size(), specifierLen.size()); int declaratorCount = __min(declStart.size() , declLen.size()); // check AST: checkASTNodeHas ( node, ASTNodeTypes::declaration, 0, source.length(), sourceLine, "ASTNodeTypes::declaration" ); if (specifierCount>0) checkASTNodePropertyHas( node, ASTNodeProperties::declarationSpecifiersProperty, ASTNodeTypes::declarationSpecifierList, specifierStart[0], specifierLen[specifierCount-1]+specifierStart[specifierCount-1]-specifierStart[0], sourceLine, "ASTNodeProperties::declarationSpecifiersProperty" ); ASTNodePtr specifierList = node->getProperty(ASTNodeProperties::declarationSpecifiersProperty); // check number of specifiers parsed: CppUnit::assertEquals( specifierList->getChildCount(), specifierCount, sourceLine, boost::io::str(boost::format("Bad number of specifiers:\n Actual %1%\n Expected %2%.") % specifierList->getChildCount() % specifierCount ) ); int idx; for (idx=0; idx<specifierCount; idx++) { ASTNodePtr specifierNode = specifierList->getChildAt(idx); CppUnit::assertEquals( specifierStart[idx], specifierNode->getStartIndex(), sourceLine, boost::io::str(boost::format("Specifier %1%: bad node start index.") % idx) ); CppUnit::assertEquals( specifierLen[idx] , specifierNode->getLength(), sourceLine, boost::io::str(boost::format("Specifier %1%: bad node length.") % idx) ); } // check declarators CppUnit::assertEquals( node->getChildCount() , declaratorCount , sourceLine, "Wrong number of declarators." ); for (idx=0; idx<declaratorCount; idx++) { ASTNodePtr declNode = node->getChildAt(idx); CppUnit::assertEquals( declStart[idx], declNode->getStartIndex(), sourceLine, boost::io::str(boost::format("Declarator %1%: bad node start index.") % idx) ); CppUnit::assertEquals( declLen[idx] , declNode->getLength(), sourceLine, boost::io::str(boost::format("Declarator %1%: bad node length.") % idx) ); } } } // namespace Testing #define RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ) \ Refactoring::Testing::checkDeclarationMutatorPass( source, CPPUNIT_SOURCELINE() ) #define RFTA_ASSERT_DECLARATION( source,sourceAST,specStart,specLen,declaratorStart,declaratorLen )\ Refactoring::Testing::checkDeclaration( \ source, sourceAST, specStart, specLen, \ declaratorStart, declaratorLen, CPPUNIT_SOURCELINE() ) UnparsedDeclarationMutatorTest::UnparsedDeclarationMutatorTest() : CppUnit::TestFixture() { } UnparsedDeclarationMutatorTest::~UnparsedDeclarationMutatorTest() { } void UnparsedDeclarationMutatorTest::setUp() { } void UnparsedDeclarationMutatorTest::tearDown() { } template<typename T> std::vector<T>& operator<< (std::vector<T>& list, T val) { list.push_back(val); return list; } template std::vector<int>& operator<<(std::vector<int>&, int); void UnparsedDeclarationMutatorTest::testSimpleDeclaration() { const std::string source( "const short int std::x;" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0 << 6 << 12; specLen << 5 << 5 << 3 ; declStart << 16; declLen << 6; SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::simpleTypeSpecifier ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(1), ASTNodeTypes::simpleTypeSpecifier); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(2), ASTNodeTypes::simpleTypeSpecifier); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator ); } void UnparsedDeclarationMutatorTest::testFunctionDeclaration() { const std::string source( "int fct(int p1, unsigned int p2, typename tp<int> p3);" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << 3; declStart << 4; declLen << int(source.length()-5); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::simpleTypeSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator ); } void UnparsedDeclarationMutatorTest::testClassDeclaration() { const std::string source( "class x { public: int x() { } } y;" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(source.length()-3); declStart << int(source.length()-2); declLen << 1; SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::classSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator ); } void UnparsedDeclarationMutatorTest::testClassDeclarationWithInheritance() { const std::string source( "class x: public std::c1, protected user::c3 { public: int x() { } };" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(source.length()-1); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::classSpecifier ); } void UnparsedDeclarationMutatorTest::testEnumDeclaration() { const std::string source( "enum x { a = 0, b, c };" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(source.length()-1); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::enumSpecifier ); } void UnparsedDeclarationMutatorTest::testPointerDecl() { const std::string source( "int *f;" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << 3; declStart << 4; declLen << 2; SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::simpleTypeSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testFctPointer() { const std::string source( "int (*f)(int);" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << 3; declStart << 4; declLen << int(std::string("(*f)(int)").size()); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::simpleTypeSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testUserTypeFctPointer() { const std::string source( "usertype (*f)(int x);" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << 8; declStart << 9; declLen << int(std::string("(*f)(int x)").size()); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::simpleTypeSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testSimpleTemplate() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "std::vector< std::vector<int> >" #define DECLARATOR "&v = par_0" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::simpleTypeSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testParameterTemplate() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "usertmpl<int>(0,1)" #define DECLARATOR "&v" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::simpleTypeSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testSpecialNestedName() { /* EXAMPLE FOR THIS TEST: typedef int myint; class x { public: static myint y; }; myint ::x::y; btw: spaces are allowed between '::' and idenfifier ("x ::y" equals "x::y") "class x ::z::y" has also two meanings ! */ #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "myint" #define DECLARATOR "::x::y" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::simpleTypeSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testElaboratedClass() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "class ::x::x1::x3" #define DECLARATOR "y" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::elaboratedTypeSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testElaboratedUnion() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "union y::x" #define DECLARATOR "" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::elaboratedTypeSpecifier ); } void UnparsedDeclarationMutatorTest::testUnnamedStruct() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "struct { int x; }" #define DECLARATOR "z" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::classSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testDeclareOperator() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "int" #define DECLARATOR "operator<<(class T, int)" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check specifier types: ASTNodePtr specifierList = node->getProperty( ASTNodeProperties::declarationSpecifiersProperty ); RFTA_ASSERT_NODE_TYPE( specifierList->getChildAt(0), ASTNodeTypes::simpleTypeSpecifier ); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testConvertOperator() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "" #define DECLARATOR "operator short int() (class T)" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testDetectFunctionPtr() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "mytype" #define DECLARATOR "* (*fct)(int, float) = &impl" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testDetectUserDefType_Ptr() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "mytype" #define DECLARATOR "* f(int)" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testDetectUserDefType_Ref() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "mytype" #define DECLARATOR "& f(int)" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0; specLen << int(strlen( SPECIFIER )); declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testDeclaringConst() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "const mytype" #define DECLARATOR "* const f(int) const" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0 << 6; specLen << 5 << 6; declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testDeclaringExceptions() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "vector<int>" #define DECLARATOR "& f(int) throw( BadParamExcep, OtherExcep )" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0 ; specLen << 11 ; declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testDeclaringArray() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "short int" #define DECLARATOR "xyz[3][3] = { { 3,3,3 } , { 4,4,4 } , { 5,5,5 } }" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0 << 6 ; specLen << 5 << 3 ; declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testTypedefDeclaration() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "typedef short int" #define DECLARATOR "mydef" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0 << 8 << 14; specLen << 7 << 5 << 3; declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } void UnparsedDeclarationMutatorTest::testStructTypedef() { #undef SPECIFIER #undef DECLARATOR #define SPECIFIER "struct c { int a; } typedef" #define DECLARATOR "mystruct" const std::string source( SPECIFIER " " DECLARATOR ";" ); std::vector<int> specStart, declStart; std::vector<int> specLen , declLen; specStart << 0 << 20 ; specLen << 19 << 7 ; declStart << int(strlen( SPECIFIER ))+1; declLen << int(strlen( DECLARATOR )); SourceASTNodePtr sourceAST = RFTA_ASSERT_DECLARATION_MUTATOR_PASS( source ); ASTNodePtr node = sourceAST->getChildAt(0); // check AST: RFTA_ASSERT_DECLARATION(source,sourceAST,specStart,specLen,declStart,declLen); // check declarator types: RFTA_ASSERT_NODE_TYPE( node->getChildAt(0), ASTNodeTypes::unparsedDeclarator); } } // namespace Refactoring --- NEW FILE: UnparsedDeclarationMutator.h --- // ////////////////////////////////////////////////////////////////////////// // Header file UnparsedDeclarationMutator.h for class UnparsedDeclarationMutator // (c)Copyright 2003, Andre Baresel. // Created: 2003/04/18 // ////////////////////////////////////////////////////////////////////////// #ifndef RFTA_UnparsedDeclarationMutator_H #define RFTA_UnparsedDeclarationMutator_H #include <rfta/parser/Parser.h> #include <set> namespace Refactoring { /// Mutate an unparsed-declaration-list into a parsed declaration-list class UnparsedDeclarationMutator : public Parser { public: /*! Constructs a UnparsedDeclarationMutator object. * * source range must not start with white spaces. */ UnparsedDeclarationMutator( ParseContext &context, const ASTNodePtr &node, const SourceASTNodePtr &sourceNode); /// Destructor. virtual ~UnparsedDeclarationMutator(); bool tryMutate(); private: // // private methods for type specifier parsing: // // ENTRY-Point: void parseDeclarationSpecifierList(ASTNodePtr &specifierList); // parsing of composed specifiers (e.g. "class x { ... }" void parseComposedSpecifier(const char * specifierStart, std::string& specifierIdent, ASTNodePtr &specifierList); /** * function does try to read a user defined type (it checks for a variable * declaration) * returns false in case of the end of specifier list */ bool tryParseUserDefinedType(std::string& typename_); void readNestedName(std::string& nestedname); void readClassOrEnumSpecifier(ASTNodePtr& specifier, std::string keyword, std::string name); // // private methods for declarator parsing: // // ENTRY-Point: void parseDeclarators(); void parseOperator(); bool tryReadToken(std::string& token); bool doesKeywordFollow( std::string keyword ); static bool tryFindNextBalanced( const char *¤t, const char *end, char opening = '<', char closing = '>' ); bool skipOverAssignmentInitializer(); void createAndAddInitializerNode( const ASTNodePtr &variableDeclNode ); void addValueNode( const ASTNodePtr& variableDeclNode, int start, int end ) const; void addInitializerNode( const ASTNodePtr& variableDeclNode, const ASTNodeType initializerType, int initializerStartIndex ) const; private: ASTNodePtr node_; typedef std::set<std::string> KeywordSet; KeywordSet declarationSpecifiers; KeywordSet elaboratedSpecifiers; }; // Inlines methods for UnparsedDeclarationMutator: // -------------------------------------------- } // namespace Refactoring #endif // RFTA_UnparsedDeclarationMutator_H --- NEW FILE: UnparsedDeclarationMutator.cpp --- // ////////////////////////////////////////////////////////////////////////// // Implementation file UnparsedDeclarationMutator.cpp for class UnparsedDeclarationMutator // (c)Copyright 2003, Andre Baresel. // Created: 2003/04/18 // ////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "UnparsedDeclarationMutator.h" #include <rfta/parser/ASTNodes.h> #include <rfta/parser/ParseContext.h> #include <rfta/parser/DeclarationListParser.h> namespace Refactoring { UnparsedDeclarationMutator::UnparsedDeclarationMutator( ParseContext &context, const ASTNodePtr &node, const SourceASTNodePtr &sourceNode) : Parser( context, sourceNode->getBlankedSourceStart() + node->getRange().getStartIndex(), sourceNode->getBlankedSourceStart() + node->getRange().getEndIndex() ) , node_( node ) { // build lookup table for specifiers: // generel specifier: declarationSpecifiers.insert("typedef"); declarationSpecifiers.insert("friend"); // storage class declarationSpecifiers.insert("auto"); declarationSpecifiers.insert("register"); declarationSpecifiers.insert("static"); declarationSpecifiers.insert("extern"); declarationSpecifiers.insert("mutable"); // function specifiers declarationSpecifiers.insert("inline"); declarationSpecifiers.insert("virtual"); declarationSpecifiers.insert("explicit"); // simple type specifiers declarationSpecifiers.insert("char"); declarationSpecifiers.insert("wchar_t"); declarationSpecifiers.insert("bool"); declarationSpecifiers.insert("short"); declarationSpecifiers.insert("int"); declarationSpecifiers.insert("long"); declarationSpecifiers.insert("signed"); declarationSpecifiers.insert("unsigned"); declarationSpecifiers.insert("float"); declarationSpecifiers.insert("double"); declarationSpecifiers.insert("void"); // cv-qualifier declarationSpecifiers.insert("const"); declarationSpecifiers.insert("volatile"); // build lookup table for elaborated specifiers: elaboratedSpecifiers.insert("class"); elaboratedSpecifiers.insert("struct"); elaboratedSpecifiers.insert("enum"); elaboratedSpecifiers.insert("union"); elaboratedSpecifiers.insert("typename"); } UnparsedDeclarationMutator::~UnparsedDeclarationMutator() { } bool UnparsedDeclarationMutator::tryMutate() { ASTNodePtr declarationNode = node_; node_->mutateType( ASTNodeTypes::declaration ); ASTNodePtr specifierList = createASTNode( ASTNodeTypes::declarationSpecifierList, declarationNode, getCurrentIndex(), getCurrentLength() ); declarationNode->setPropertyNode( ASTNodeProperties::declarationSpecifiersProperty, specifierList ); // read the declaration specifier list and add childs to property: parseDeclarationSpecifierList(specifierList); backtrackSkippingSpaces(); specifierList->setLength(getCurrentLength()); skipSpaces(); // check if declaration has also a declarator: if (!tryNextIs(';')) { // read all declarators and add childs to property: parseDeclarators(); } // return with no parsing error: return true; } /** * function parses all declaration specifiers until the first declarator is found. * the decision about the end of the specifier list is done in "tryParseUserDefinedType" */ void UnparsedDeclarationMutator::parseDeclarationSpecifierList(ASTNodePtr &specifierList) { std::string identifier; const char * save_pointer = getCurrent(); while ( save_pointer = getCurrent(), tryReadNextIdentifier(identifier) ) { if (declarationSpecifiers.find(identifier) != declarationSpecifiers.end()) { // add the specifier node ASTNodePtr specifier = createASTNode( ASTNodeTypes::simpleTypeSpecifier, specifierList, save_pointer-getStart(), getCurrent()-save_pointer ); specifierList->addChild(specifier); skipSpaces(); continue; } // check elaborated-specifiers: else if (elaboratedSpecifiers.find(identifier) != elaboratedSpecifiers.end()) { skipSpaces(); parseComposedSpecifier(save_pointer, identifier, specifierList); skipSpaces(); continue; } else // check characters after symbol to find out if it's a userdefined type... if (tryParseUserDefinedType(identifier)) { backtrackSkippingSpaces(); // add the specifier node ASTNodePtr specifier = createASTNode( ASTNodeTypes::simpleTypeSpecifier, specifierList, save_pointer-getStart(), getCurrent()-save_pointer ); specifierList->addChild(specifier); skipSpaces(); continue; } else { current_ = save_pointer; break; } } } /** * function tries to parse elaborated and class/enum/struct/union specifiers * a decision about the type is found during parsing. */ void UnparsedDeclarationMutator::parseComposedSpecifier(const char * specifierStart, std::string& specifierIdent, ASTNodePtr &specifierList) { // CASE 1: // check if identifier starts with a '::') // (definitions can not start with nested names -> this declaration is an elaborated type // which ends after the name) if (tryNextIs(':')) { if (!tryNextIs(':')) { throwFailure( "Expected a double colon => '::'." ); } skipSpaces(); // read the full name: std::string name("::"); readNestedName(name); // add the specifier node ASTNodePtr specifier = createASTNode( ASTNodeTypes::elaboratedTypeSpecifier, specifierList, specifierStart-getStart(), getCurrent()-specifierStart ); specifierList->addChild(specifier); return; // FINISH HERE } // try to read the identifier that can be specifier after an elaborated type specifier // if no identifier follows, an unnamed type is specifier (e.g. "struct { } x;") std::string secondIdent; if (tryReadNextIdentifier(secondIdent)) { skipSpaces(); } // check if no identifier or the identifier is not followed by a ':' (e.g. "class x {" if (secondIdent.empty() || !tryNextIs(':')) { // add the specifier node ASTNodePtr specifier = createASTNode( ASTNodeTypes::classSpecifier, specifierList, specifierStart-getStart(), getCurrent()-specifierStart ); specifierList->addChild(specifier); readClassOrEnumSpecifier(specifier, specifierIdent, secondIdent); // set real length after completed parsing specifier->setLength(getCurrent()-specifierStart); return; } // HERE we come only in case where the type is followed by a colon. "e.g. class x:" // check if it is only a single colon (which means inheritance information e.g. "class x: public y ") if (!tryNextIs(':')) { // yes it's - so parse the class specifier if (specifierIdent == "class" || specifierIdent == "struct") { // add the specifier node ASTNodePtr specifier = createASTNode( ASTNodeTypes::classSpecifier, specifierList, specifierStart-getStart(), getCurrent()-specifierStart ); specifierList->addChild(specifier); // read the complete specifier: readClassOrEnumSpecifier(specifier, specifierIdent, secondIdent); // set real length after completed parsing specifier->setLength(getCurrent()-specifierStart); return; // FINISH HERE (the class specifier ends here !) } throwFailure( "Expected a double colon => '::'." ); } // HERE we come only in case of a double colon after the identifier which means: // an elaborated type is specified: e.g. "class x::y" skipSpaces(); // read the full name: secondIdent.append("::"); readNestedName(secondIdent); // add the specifier node ASTNodePtr specifier = createASTNode( ASTNodeTypes::elaboratedTypeSpecifier, specifierList, specifierStart-getStart(), getCurrent()-specifierStart ); specifierList->addChild(specifier); // set real length after completed parsing specifier->setLength(getCurrent()-specifierStart); } bool UnparsedDeclarationMutator::tryParseUserDefinedType(std::string& typename_) { // the 'typename_' might be a userdefined type or a declarator // here we try to find out: const char * rollback = current_; if (typename_ == "operator") return false; // first read the fully qualified name: skipSpaces(); // maybe a full qualified typename (e.g. "std::string") if (tryNextIs(':')) { if (!tryNextIs(':')) throwFailure("Declaration parser expects '::' in this context."); typename_.append("::"); readNestedName(typename_); skipSpaces(); } // now check for template declaration: if (tryNextIs('<')) // the use of a template type { // skip template usage: findNextBalanced('<','>'); skipSpaces(); // check if it has parameter: if (tryNextIs('(')) if (!this->tryReadUntilNext(')')) throwFailure("Expect a closed parameter list for this template."); return true; // yes, it's a user defined type ! } // DO SOME LOOK AHEAD TO FIND OUT // a possible declarator that follows: // check existence of a next identifier, this is a sign for a userdefined type... std::string identifier; if (tryReadNextIdentifier(identifier)) { current_ = rollback; return true; } // check for a special case where the declarator starts with a '(' // example: "int (*(*f))(int); if (tryNextIs('(')) // might be the declarator (e.g. "usertype (*f);" or a parameter (e.g. "int userfct()"; { findNextBalanced('(',')'); } skipSpaces(); std::string seperators=",;=["; bool ret = seperators.find(*current_) == std::string::npos; current_ = rollback; return ret; } void UnparsedDeclarationMutator::readNestedName(std::string& nestedname) { std::string fullName = nestedname; std::string nameSpecifier; bool oneMoreLevel; do { oneMoreLevel = false; if (!tryReadNextIdentifier(nameSpecifier)) throwFailure( "Expected an identifier for elaborated type." ); fullName.append(nameSpecifier); skipSpaces(); // check if identifier is followed by a '::' (additional level if (tryNextIs(':')) { if (!tryNextIs(':')) throwFailure( "Expected a double colon => '::'." ); fullName.append("::"); skipSpaces(); oneMoreLevel = true; } } while (oneMoreLevel); backtrackSkippingSpaces(); } void UnparsedDeclarationMutator::readClassOrEnumSpecifier(ASTNodePtr& specifier, std::string keyword, std::string name) { if (keyword == "class" || keyword == "struct" ) { // read over possible inheritance information readUntilNextOf("{"); current_++; } else { specifier->mutateType( ASTNodeTypes::enumSpecifier ); expect('{'); } findNextBalanced('{','}'); } bool UnparsedDeclarationMutator::tryFindNextBalanced( const char *¤t, const char *end, char opening, char closing ) { int balance = 1; while ( ++current != end ) { char c = *current; if ( c == closing ) { --balance; if ( balance == 0 ) { ++current; return true; } } else if ( c == opening ) ++balance; } return false; } bool UnparsedDeclarationMutator::skipOverAssignmentInitializer() { const char *start = current_; while ( current_ != end_ ) { char c = *current_; if ( c == ';' || c == ',' ) return current_ != (start+1); else if ( c == '(' ) { if ( !tryFindNextBalanced( current_, end_, '(', ')' ) ) return false; } else if ( c == '[' ) { if ( !tryFindNextBalanced( current_, end_, '[', ']' ) ) return false; } else if ( c == '{' ) { if ( !tryFindNextBalanced( current_, end_, '{', '}' ) ) return false; } else ++current_; } return true; } void UnparsedDeclarationMutator::parseDeclarators() { Tracker tracker( "UnparsedDeclarationMutator::parseDeclarators", *this ); int declaratorNumber = 1; int prefixEndIndex = getCurrentIndex(); while ( current_ != end_ ) { skipSpaces(); int declaratorStartIndex = getCurrentIndex(); if (doesKeywordFollow( "operator" )) { parseOperator(); return; } // find end of the init-declarator bool declaratorEndReached = false; bool functionDeclarator = false; bool identifierFound = false; do { skipSpaces(); if (tryNextIs('*')) continue; if (tryNextIs('&')) continue; if (tryNextIs('(')) { // check if this is a direct declaration of a function: if (identifierFound) { functionDeclarator = true; findNextBalanced('(',')'); } else { findNextBalanced('(',')'); readUntilNextOf(";,=("); if (tryNextIs('(')) { functionDeclarator = true; findNextBalanced('(',')'); } } declaratorEndReached = true; break; } if (tryNextIs('[')) { findNextBalanced('[',']'); continue; } if (tryNextIs(';') || tryNextIs(',') || tryNextIs('=') || tryNextIs('{')) { declaratorEndReached = true; --current_; break; } std::string nestedName; if (tryNextIs(':')) { if (!tryNextIs(':')) throwFailure("Did not expect a single colon at this stage."); nestedName = "::"; } std::string identifier; if (!tryReadNextIdentifier(identifier)) { throwFailure( boost::format("unexpected character: '%1%'.") % *current_ ); } else { if (identifier=="const") continue; if (identifier=="volatile") continue; identifierFound = true; // read fully qualified name: nestedName.append(identifier); if (tryReadNext("::")) { nestedName.append("::"); readNestedName(identifier); } continue; } } while (hasNext() && !declaratorEndReached); if (!declaratorEndReached) { boost::format frmt( "failed to find expected declarator separator " "for declaration %1%: ',;=({'. "); throwFailure( frmt % declaratorNumber ); } if (functionDeclarator) { // read the possible identifiers after function declarator: bool found; do { skipSpaces(); found=false; if (doesKeywordFollow("const") ) { found=true; } if (doesKeywordFollow("volatile") ) { found=true; } } while (found); if (doesKeywordFollow("throw")) { skipSpaces(); expect('('); readUntilNextOf(")"); if (*current_==')') ++current_; } } ASTNodePtr declaratorNode = createASTNode( ASTNodeTypes::unparsedDeclarator, node_, declaratorStartIndex, getCurrentIndex() - declaratorStartIndex ); // the correct length is set when the initializer is added. node_->addChild(declaratorNode); // now go through initializers: createAndAddInitializerNode(declaratorNode); declaratorNumber++; } } void UnparsedDeclarationMutator::createAndAddInitializerNode( const ASTNodePtr &declaratorNode ) { if ( !hasNext() ) return; Tracker tracker( "UnparsedDeclarationMutator::createAndAddInitializerNode", *this ); int initializerStartIndex = getCurrentIndex(); int initializerValueStartIndex; int initializerValueEndIndex; int declaratorEndIndex; ASTNodeType initializerType; switch( *current_++ ) { case '=': initializerType = ASTNodeTypes::assignVariableInitializerExpression; skipSpaces(); initializerValueStartIndex = getCurrentIndex(); skipOverAssignmentInitializer(); /// @todo should check return value declaratorEndIndex = getCurrentIndex(); initializerValueEndIndex = getCurrentIndex(); break; case '(': initializerType = ASTNodeTypes::constructorVariableInitializerExpression; initializerValueStartIndex = getCurrentIndex(); findNextBalanced( '(', ')' ); declaratorEndIndex = getCurrentIndex(); initializerValueEndIndex = getCurrentIndex() -1; break; case ';': case ',': case '{': return; default: -- current_; throwFailure( boost::format("unexpected character: '%1%'.") % *current_ ); } declaratorNode->setLength( declaratorEndIndex - declaratorNode->getStartIndex() ); addInitializerNode( declaratorNode, initializerType, initializerStartIndex ); addValueNode( declaratorNode, initializerValueStartIndex, initializerValueEndIndex ); skipSpaces(); if ( !hasNext() ) return; if ( *current_ == ';' || *current_ == ',' ) ++current_; else throwFailure( boost::format("unexpected character: '%1%'.") % *current_ ); } void UnparsedDeclarationMutator::addValueNode( const ASTNodePtr& declaratorNode, int start, int end) const { ASTNodePtr initializerNode = declaratorNode->getProperty( ASTNodeProperties::variableInitializerProperty ); ASTNodePtr valueNode = createASTNode( ASTNodeTypes::valueExpression, initializerNode, start, end-start); initializerNode->setPropertyNode( ASTNodeProperties::valueProperty, valueNode ); } void UnparsedDeclarationMutator::addInitializerNode( const ASTNodePtr& declaratorNode, const ASTNodeType initializerType, int initializerStartIndex) const { int initializerLength = getCurrentIndex() - initializerStartIndex; ASTNodePtr initializerNode = createASTNode( initializerType, declaratorNode, initializerStartIndex, initializerLength ); declaratorNode->setPropertyNode( ASTNodeProperties::variableInitializerProperty, initializerNode ); } bool UnparsedDeclarationMutator::doesKeywordFollow( std::string keyword) { int idx = 0; const char * save = getCurrent(); std::string id; bool retval = tryReadNextIdentifier(id) & id == keyword; if (!retval) current_ = save; return retval; } bool UnparsedDeclarationMutator::tryReadToken(std::string& token) { std::string collect; switch(*current_++) { case '+': if (*current_== '=' ) { current_++; collect="+="; } else if (*current_== '+' ) { current_++; collect="++"; } else collect="+"; break; case '-': if (*current_== '=' ) { current_++; collect="-="; } else if (*current_== '-' ) { current_++; collect="--"; } else if (*current_== '>' ) { current_++; if (*current_== '*' ) { current_++; collect="->*"; } else collect="->"; } else collect="-"; break; case '*': if (*current_== '=' ) { current_++; collect="*="; } else collect="*"; break; case '/': if (*current_== '=' ) { current_++; collect="/="; } else collect="/"; break; case '^': if (*current_== '=' ) { current_++; collect="^="; } else collect="^"; break; case '&': if (*current_== '=' ) { current_++; collect="&="; } else if (*current_== '&' ) { current_++; collect="&&"; } else collect="&"; break; case '|': if (*current_== '=' ) { current_++; collect="|="; } else if (*current_== '|' ) { current_++; collect="||"; } else collect="|"; break; case '~': collect="~"; break; case '!': if (*current_== '=' ) { current_++; collect="!="; } else collect="!"; break; case '=': if (*current_== '=' ) { current_++; collect="=="; } else collect="="; break; case '<': if (*current_== '=' ) { current_++; collect="<="; } else if (*current_== '<' ) { current_++; if (*current_== '=' ) { current_++; collect="<<="; } else collect="<<"; } else collect="<"; break; case '>': if (*current_== '=' ) { current_++; collect=">="; } else if (*current_== '>' ) { current_++; if (*current_== '=' ) { current_++; collect=">>="; } else collect=">>"; } else collect=">"; break; case ',': collect=","; break; case '(': expect(')'); collect="()"; break; case '[': expect(']'); collect="[]"; break; default: --current_; break; } token = collect; return !token.empty(); } void UnparsedDeclarationMutator::parseOperator() { int declaratorStartIndex = getCurrentIndex() - strlen("operator"); skipSpaces(); std::string token; if (!tryReadToken(token)) { const char * begin = getCurrent(); if ( doesKeywordFollow("new") ) token += "new"; if ( doesKeywordFollow("delete") ) token += "delete"; if (!token.empty()) { if ( tryReadNext("[]") ) token+="[]"; } } // check if operator overloading has been parsed if (token.empty()) { // this is not the case. // this is 'conversion function declarator': // skip over the type-specifier and ptr-operator elements readUntilNextOf("("); if ( !tryReadNext("()") ) throwFailure( "Expect '()' after a conversion function operator" ); } // now read parameters: (for both operator and conversion function) skipSpaces(); expect('('); findNextBalanced('(',')'); ASTNodePtr declaratorNode = createASTNode( ASTNodeTypes::unparsedDeclarator, node_, declaratorStartIndex, getCurrentIndex() - declaratorStartIndex ); node_->addChild(declaratorNode); skipSpaces(); } } // namespace Refactoring |