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
|