|
From: <net...@us...> - 2003-04-29 09:55:42
|
Update of /cvsroot/cpptool/rfta/src/rftaparser
In directory sc8-pr-cvs1:/tmp/cvs-serv29065/src/rftaparser
Added Files:
DeclarationDetailsParser.h DeclarationDetailsParser.cpp
Log Message:
-- corrected "UnparsedDeclarationMutator" to be a real Mutator that
can be used by MaxLODMutator
--- NEW FILE: DeclarationDetailsParser.h ---
// //////////////////////////////////////////////////////////////////////////
// Header file DeclarationDetailsParser.h for class DeclarationDetailsParser
// (c)Copyright 2003, Andre Baresel.
// Created: 2003/04/18
// //////////////////////////////////////////////////////////////////////////
#ifndef RFTA_DeclarationDetailsParser_H
#define RFTA_DeclarationDetailsParser_H
#include <rfta/parser/Parser.h>
#include <set>
namespace Refactoring
{
/// Mutate an unparsed-declaration-list into a parsed declaration-list
class DeclarationDetailsParser : public Parser
{
public:
/*! Constructs a DeclarationDetailsParser object.
*
* source range must not start with white spaces.
*/
DeclarationDetailsParser(
ParseContext &context,
const ASTNodePtr &node,
const SourceASTNodePtr &sourceNode);
/// Destructor.
virtual ~DeclarationDetailsParser();
bool tryParse();
private:
//
// private methods for type specifier parsing:
//
// ENTRY-Point:
void parseDeclarationSpecifierList(ASTNodePtr &specifierList);
// parsing of composed specifiers (e.g. "class x { ... }"
void parseComposedSpecifier(int 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();
// parser has to stay at the character after the operator keyword...
void parseOperator(int declaratorStartIndex);
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;
static bool isOperatorIdentifier(std::string name);
private:
ASTNodePtr node_;
typedef std::set<std::string> KeywordSet;
KeywordSet declarationSpecifiers;
KeywordSet elaboratedSpecifiers;
};
// Inlines methods for DeclarationDetailsParser:
// --------------------------------------------
} // namespace Refactoring
#endif // RFTA_DeclarationDetailsParser_H
--- NEW FILE: DeclarationDetailsParser.cpp ---
// //////////////////////////////////////////////////////////////////////////
// Implementation file DeclarationDetailsParser.cpp for class DeclarationDetailsParser
// (c)Copyright 2003, Andre Baresel.
// Created: 2003/04/18
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DeclarationDetailsParser.h"
#include <rfta/parser/ASTNodes.h>
#include <rfta/parser/ParseContext.h>
#include <rfta/parser/DeclarationListParser.h>
namespace Refactoring
{
DeclarationDetailsParser::DeclarationDetailsParser(
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");
}
DeclarationDetailsParser::~DeclarationDetailsParser()
{
}
bool
DeclarationDetailsParser::tryParse()
{
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
DeclarationDetailsParser::parseDeclarationSpecifierList(ASTNodePtr &specifierList)
{
std::string identifier;
const char * save_pointer = getCurrent();
int lastIndex;
while ( save_pointer = getCurrent(),lastIndex=getCurrentIndex(), tryReadNextIdentifier(identifier) )
{
if (declarationSpecifiers.find(identifier) != declarationSpecifiers.end())
{
// add the specifier node
ASTNodePtr specifier =
createASTNode(
ASTNodeTypes::simpleTypeSpecifier,
specifierList,
lastIndex,
getCurrentIndex()-lastIndex
);
specifierList->addChild(specifier);
skipSpaces();
continue;
}
// check elaborated-specifiers:
else if (elaboratedSpecifiers.find(identifier) != elaboratedSpecifiers.end())
{
skipSpaces();
parseComposedSpecifier(lastIndex, 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,
lastIndex,
getCurrentIndex()-lastIndex
);
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
DeclarationDetailsParser::parseComposedSpecifier( int 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,
getCurrentIndex()-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,
getCurrentIndex()-specifierStart
);
specifierList->addChild(specifier);
readClassOrEnumSpecifier(specifier, specifierIdent, secondIdent);
// set real length after completed parsing
specifier->setLength(getCurrentIndex()-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" || specifierIdent == "union")
{
// add the specifier node
ASTNodePtr specifier =
createASTNode(
ASTNodeTypes::classSpecifier,
specifierList,
specifierStart,
getCurrentIndex()-specifierStart
);
specifierList->addChild(specifier);
// read the complete specifier:
readClassOrEnumSpecifier(specifier, specifierIdent, secondIdent);
// set real length after completed parsing
specifier->setLength(getCurrentIndex()-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,
getCurrentIndex()-specifierStart
);
specifierList->addChild(specifier);
// set real length after completed parsing
specifier->setLength(getCurrentIndex()-specifierStart);
}
bool
DeclarationDetailsParser::tryParseUserDefinedType(std::string& typename_)
{
// the 'typename_' might be a userdefined type or a declarator
// here we try to find out:
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(':'))
{
--current_;
return false; // it's not "::" - might be the bitfield operator (e.g. "int myvar:0")
}
typename_.append("::");
readNestedName(typename_);
skipSpaces();
// check for member operator: e.g. "x::operator"
if (isOperatorIdentifier(typename_))
{
return false;
}
}
// do some look ahead for the decision (store rollback position
const char * rollback = current_;
// 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) const;"
if (tryNextIs('(')) // might be the declarator (e.g. "usertype (*f);" or a parameter (e.g. "int userfct()";
{
findNextBalanced('(',')');
}
// check the characters follow the braces:
skipSpaces();
if (tryReadNextIdentifier(identifier))
{
// the "const" keyword is allowed for function declarations
if (identifier!="const")
{
// but it's not the 'const'
current_ = rollback;
return false; // this was not a function-declarator,
}
}
std::string seperators=",;=[";
bool ret = seperators.find(*current_) == std::string::npos;
current_ = rollback;
return ret;
}
void
DeclarationDetailsParser::readNestedName(std::string& nestedname)
{
std::string nameSpecifier;
bool oneMoreLevel;
do {
oneMoreLevel = false;
if (!tryReadNextIdentifier(nameSpecifier))
throwFailure( "Expected an identifier for elaborated type." );
nestedname.append(nameSpecifier);
skipSpaces();
// check if identifier is followed by a '::' (additional level
if (tryNextIs(':'))
{
if (!tryNextIs(':'))
{
--current_;
return; // // it's not a "::" - might be the bitfield operator (e.g. "int myvar::sub :0")
}
nestedname.append("::");
skipSpaces();
oneMoreLevel = true;
}
} while (oneMoreLevel);
backtrackSkippingSpaces();
}
void
DeclarationDetailsParser::readClassOrEnumSpecifier(ASTNodePtr& specifier, std::string keyword, std::string name)
{
ASTNodePtr body;
int startIndex;
if (keyword == "class" || keyword == "struct" || keyword == "union")
{
// read over possible inheritance information
readUntilNextOf("{");
current_++;
body = createASTNode(
ASTNodeTypes::unparsedDeclarationList,
specifier,
startIndex = getCurrentIndex(),
getCurrentLength()
);
specifier->setPropertyNode( ASTNodeProperties::classBodyProperty , body );
} else
{
specifier->mutateType( ASTNodeTypes::enumSpecifier );
expect('{');
body = createASTNode(
ASTNodeTypes::unparsedDeclarationList,
specifier,
startIndex = getCurrentIndex(),
getCurrentLength()
);
specifier->setPropertyNode( ASTNodeProperties::enumBodyProperty , body );
}
findNextBalanced('{','}');
body->setLength(getCurrentLength() - startIndex - 1 ); // do not count the last '}'
}
bool
DeclarationDetailsParser::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
DeclarationDetailsParser::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
DeclarationDetailsParser::parseDeclarators()
{
Tracker tracker( "DeclarationDetailsParser::parseDeclarators", *this );
int declaratorNumber = 1;
while ( current_ != end_ )
{
skipSpaces();
int declaratorStartIndex = getCurrentIndex();
// 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(nestedName);
}
// check for operator keyword:
if (isOperatorIdentifier(nestedName))
{
parseOperator(declaratorStartIndex);
return;
}
// check for bitfield expression
if (tryNextIs(':'))
{
if (!skipOverAssignmentInitializer())
throwFailure("Constant expression is not well formed.");
// @todo: store bit field expression
}
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
DeclarationDetailsParser::createAndAddInitializerNode( const ASTNodePtr &declaratorNode )
{
if ( !hasNext() )
return;
Tracker tracker( "DeclarationDetailsParser::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
DeclarationDetailsParser::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
DeclarationDetailsParser::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
DeclarationDetailsParser::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
DeclarationDetailsParser::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
DeclarationDetailsParser::parseOperator(int declaratorStartIndex)
{
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("(");
}
// now read parameters: (for both operator and conversion function)
skipSpaces();
expect('(');
findNextBalanced('(',')');
readUntilNextOf("{;=,");
backtrackSkippingSpaces();
ASTNodePtr declaratorNode = createASTNode( ASTNodeTypes::unparsedDeclarator,
node_,
declaratorStartIndex,
getCurrentIndex() - declaratorStartIndex );
node_->addChild(declaratorNode);
skipSpaces();
}
bool
DeclarationDetailsParser::isOperatorIdentifier(std::string name)
{
unsigned int pos = name.find_last_of(":");
if (pos == std::string::npos)
return name=="operator";
return name.substr(pos+1) == "operator";
}
} // namespace Refactoring
|