|
From: <net...@us...> - 2003-12-16 13:47:03
|
Update of /cvsroot/cpptool/rfta/src/rftaparser
In directory sc8-pr-cvs1:/tmp/cvs-serv28898/src/rftaparser
Added Files:
MacroReplaceRegistration.cpp PreProcessor.cpp
PreProcessorError.cpp PreProcessorTest.cpp PreProcessorTest.h
PreProcessResolver.cpp PreProcessResolver.h
PreProcessResolverTest.cpp PreProcessResolverTest.h
Log Message:
-- files of a preprocessor implementation
--- NEW FILE: MacroReplaceRegistration.cpp ---
// //////////////////////////////////////////////////////////////////////////
// Source file MacroReplaceRegistration.cpp for class MacroReplaceRegistration
// (c)Copyright 2003, Andre Baresel
// Created: 2003/12/14
// //////////////////////////////////////////////////////////////////////////
#pragma warning( disable: 4786 )
#include <rfta/parser/MacroReplaceRegistration.h>
#include <utility>
namespace Refactoring {
void
MacroReplaceRegistration::macroReplacement( const SourceRange position,
const std::string ¯o,
const std::string &replacement )
{
MacroReplacement entry;
entry.position_ = position;
entry.macroText_ = macro;
entry.replacement_ = replacement;
macroReplacements_.push_back(entry);
}
/**
* @return number of entries in registration
*/
int
MacroReplaceRegistration::getSize() const
{
return macroReplacements_.size();
}
/**
* @return an entry of the registered replacements
* @throw std::invalid_argument if index >= size.
*/
MacroReplaceRegistration::MacroReplacement
MacroReplaceRegistration::getEntry(unsigned int index) const
{
if (index >= getSize())
throw std::invalid_argument("Index out of bound within [MacroReplaceRegistration::getEntry].");
return macroReplacements_[index];
}
struct MacroReplaceRegistration::SortPredicate
{
bool operator()( const MacroReplacement &x,
const MacroReplacement &y ) const
{
return x.position_.getStartIndex() < y.position_.getStartIndex();
}
};
/**
* does prepare the data after all replacements have been done.
*/
void
MacroReplaceRegistration::finishUpData()
{
std::stable_sort( macroReplacements_.begin(), macroReplacements_.end(), SortPredicate() );
}
/**
* @return the text delta of all macro replacements before 'position')
*/
int
MacroReplaceRegistration::getReplacementDeltaBefore(SourceRange position)
{
MacroReplacement elem;
elem.position_ = position;
MacroReplacementList::iterator pos =
std::lower_bound(macroReplacements_.begin(), macroReplacements_.end(), elem );
int sum = 0;
MacroReplacementList::iterator i = macroReplacements_.begin();
while (i != pos)
{
const MacroReplacement & val = (*i);
sum+= val.macroText_.size() - val.replacement_.size();
i++;
}
return sum;
}
bool operator<(const MacroReplaceRegistration::MacroReplacement &x,const MacroReplaceRegistration::MacroReplacement &y )
{
return x.position_.getStartIndex() < y.position_.getStartIndex();
}
} // namespace
--- NEW FILE: PreProcessor.cpp ---
// //////////////////////////////////////////////////////////////////////////
// Source file PreProcessor.h for class PreProcessor
// (c)Copyright 2003, Andre Baresel
// Created: 2003/12/13
// //////////////////////////////////////////////////////////////////////////
#include <string>
#include <rfta/parser/PreProcessor.h>
#include <xtl/Type.h>
#include <xtl/CStringView.h>
#include <rfta/parser/SourceRange.h>
#include <rfta/parser/ParserTools.h>
#include "PreProcessResolver.h"
#include <rfta/parser/NonSemanticBlanker.h>
namespace Refactoring
{
PreProcessor::PreProcessor( const std::string &textToPreProcess):
toPreProcess_(textToPreProcess)
{
}
/**
* does tokenize the string, skipping strings and symbols.
* only identifiers will be checked for macro identifiers.
*
*/
std::string
PreProcessor::process(MacroReplaceListener& listener)
{
std::string preprocessed;
std::string blanked(toPreProcess_);
// first blank the source code
PreProcessResolverPtr pResolver(new PreProcessResolver());
NonSemanticBlanker blanker(toPreProcess_, blanked, pResolver);
blanker.blank();
// now do the preprocessing
const char * start = blanked.c_str();
const char * end = start + blanked.length();
bool foundIdentifier;
const char * current = start;
do
{
const char * lastpos = current;
int identlen = 0;
foundIdentifier = false;
while (current != end && !ParserTools::isIdentifierLetter(*current))
{
current++;
}
if (current != end && ParserTools::isValidIdentifierFirstLetter(*current))
{
foundIdentifier = true;
while (current+identlen != end && ParserTools::isIdentifierLetter(*(current+identlen)))
identlen++;
}
else
// this is a number - skip:
while (current != end && ParserTools::isIdentifierLetter(*current))
current++;
if (foundIdentifier)
{
// copy the skipped characters:
preprocessed += std::string( lastpos,current-lastpos);
// do the replacement:
std::string ident(current,identlen);
if (pResolver->isMacroIdentifier(ident))
{
// replace
std::string replacement = pResolver->getMacroReplacement(ident);
preprocessed += replacement;
// register macro replacement
SourceRange position(current-start,identlen);
listener.macroReplacement(position,ident,replacement);
} else
// keep it, this is no macro
preprocessed += ident;
current+=identlen;
} else
{
// copy the last characters:
preprocessed += std::string( lastpos,(end-lastpos));
}
} while (current != end);
return preprocessed;
}
} // namespace Refactoring
--- NEW FILE: PreProcessorError.cpp ---
// //////////////////////////////////////////////////////////////////////////
// Source file PreProcessorError.h for class PreProcessorError
// (c)Copyright 2003, Andre Baresel.
// Created: 2003/12/14
// //////////////////////////////////////////////////////////////////////////
#include <rfta/parser/PreProcessorError.h>
#include <string>
namespace Refactoring
{
/// Exception thrown when an error occurs during preprocessing.
PreProcessorError::PreProcessorError( const std::string &message )
: message_(message)
, what_(message)
, std::runtime_error( std::string("Preprocessing failure: ") + message )
{
}
/// Destructor.
PreProcessorError::~PreProcessorError() throw()
{
}
const char *
PreProcessorError::what() const throw()
{
return what_.c_str();
}
} // namespace Refactoring
--- NEW FILE: PreProcessorTest.cpp ---
// //////////////////////////////////////////////////////////////////////////
// Header file PreProcessorTest.h for class PreProcessorTest
// (c)Copyright 2003, Andre Baresel
// Created: 2003/12/13
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "PreProcessorTest.h"
#include <rfta/parser/PreProcessor.h>
#include <rfta/parser/MacroReplaceRegistration.h>
namespace Refactoring
{
RFTAPARSER_TEST_SUITE_REGISTRATION( PreProcessorTest );
PreProcessorTest::PreProcessorTest()
{
}
PreProcessorTest::~PreProcessorTest()
{
}
void
PreProcessorTest::setUp()
{
}
void
PreProcessorTest::tearDown()
{
}
void
PreProcessorTest::testSimpleReplace()
{
std::string source = "#define TEXT \"String\"\n\
char * var = TEXT;\n\
";
std::string expected= " \
char * var = \"String\"; ";
// do the preprocessing (use directive information)
std::string preprocessed;
PreProcessor proc(source);
MacroReplaceRegistration registration;
preprocessed = proc.process(registration);
CPPUNIT_ASSERT_EQUAL(expected, preprocessed);
CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected size of Macro-Replacement-Registration is wrong.",
1, registration.getSize());
MacroReplaceRegistration::MacroReplacement entry = registration.getEntry(0);
CPPUNIT_ASSERT_EQUAL(SourceRange(43,4),entry.position_);
}
} // namespace Refactoring
--- NEW FILE: PreProcessorTest.h ---
// //////////////////////////////////////////////////////////////////////////
// Header file PreProcessorTest.h for class PreProcessorTest
// (c)Copyright 2003, Andre Baresel
// Created: 2003/12/13
// //////////////////////////////////////////////////////////////////////////
#ifndef RFTA_PREPROCESSORTEST_H
#define RFTA_PREPROCESSORTEST_H
#include "ParserTesting.h"
namespace Refactoring
{
/// Unit tests for PreProcessor
class PreProcessorTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( PreProcessorTest );
CPPUNIT_TEST( testSimpleReplace );
CPPUNIT_TEST_SUITE_END();
public:
/*! Constructs a PreProcessorTest object.
*/
PreProcessorTest();
/// Destructor.
virtual ~PreProcessorTest();
void setUp();
void tearDown();
void testSimpleReplace();
private:
/// Prevents the use of the copy constructor.
PreProcessorTest( const PreProcessorTest &other );
/// Prevents the use of the copy operator.
void operator =( const PreProcessorTest &other );
private:
};
// Inlines methods for PreProcessorTest:
// ----------------------------------------
} // namespace Refactoring
#endif // RFTA_PREPROCESSORTEST_H
--- NEW FILE: PreProcessResolver.cpp ---
// //////////////////////////////////////////////////////////////////////////
// Source file PreProcessResolver.h for class PreProcessResolver
// (c)Copyright 2003, Andre Baresel
// Created: 2003/12/13
// //////////////////////////////////////////////////////////////////////////
#include "PreProcessResolver.h"
#include <rfta/parser/PreProcessorError.h>
#include <xtl/Type.h>
#include <xtl/CStringView.h>
#include <rfta/parser/ParserTools.h>
namespace Refactoring
{
PreProcessResolver::PreProcessResolver()
{
}
void
PreProcessResolver::parseDirective( const char *first,const char *last )
{
Xtl::CStringEnumerator en( Xtl::CStringView( first, last ) );
en.setCurrent( first );
if (strncmp(first,"#define ",8)==0)
{
// skip define keyword and spaces
first+=8;en.setCurrent( first );
ParserTools::skipSpaces(en);
Xtl::CStringView identifier;
ParserTools::tryReadIdentifier( en, identifier );
// do not understand this...
if (identifier.getLength() == 0)
ThrowPreProcessError("Do not understand syntax of this '#define' directive.");
ParserTools::skipSpaces(en);
// macro text is all but not the newline character...
addMacro(identifier.str() , std::string( en.getCurrentPos(), last-1-en.getCurrentPos()));
}
}
bool
PreProcessResolver::isMacroIdentifier( std::string identifier )
{
MacroDefMap::iterator i = macroDef_.find(identifier);
return i != macroDef_.end();
}
std::string
PreProcessResolver::getMacroReplacement( std::string macroident )
{
MacroDefMap::iterator i = macroDef_.find(macroident);
if (i == macroDef_.end())
ThrowPreProcessError(std::string("Macro '")+macroident+"'is not defined.");
return i->second;
}
void
PreProcessResolver::addMacro(std::string ident, std::string replacement)
{
macroDef_[ident] = replacement;
}
} // namespace Refactoring
--- NEW FILE: PreProcessResolver.h ---
// //////////////////////////////////////////////////////////////////////////
// Header file PreProcessResolver.h for class PreProcessResolver
// (c)Copyright 2003, Andre Baresel
// Created: 2003/12/13
// //////////////////////////////////////////////////////////////////////////
#pragma warning(disable: 4786)
#include <string>
#include <map>
#ifndef REFACTORING_PREPROCESSRESOLVER_H_INCLUDED
#define REFACTORING_PREPROCESSRESOLVER_H_INCLUDED
#include <rfta/parser/PPDirectiveListener.h>
namespace Refactoring
{
class PreProcessResolver;
typedef boost::shared_ptr<PreProcessResolver> PreProcessResolverPtr;
class PreProcessResolver: public PPDirectiveListener
{
public:
PreProcessResolver();
virtual void parseDirective( const char *first,
const char *last );
/**
* test for identifier in macro list.
*/
bool isMacroIdentifier( std::string identifier );
/**
* returns the replacement text for macro identifier
* @throw PreProcessorError if macro identifier is not defined.
*/
std::string getMacroReplacement( std::string macroident );
/**
* inserts a none parameterized macro replacement entry
*/
void addMacro(std::string ident, std::string replacement);
private:
typedef std::map< std::string , std::string > MacroDefMap;
/// storage for directives
/// 1. include information
/// 2. macro definitions
MacroDefMap macroDef_;
};
}
#endif // REFACTORING_PREPROCESSRESOLVER_H_INCLUDED
--- NEW FILE: PreProcessResolverTest.cpp ---
// //////////////////////////////////////////////////////////////////////////
// Header file PreProcessResolveTest.h for class PreProcessResolveTest
// (c)Copyright 2003, Andre Baresel
// Created: 2003/12/13
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "PreProcessResolverTest.h"
#include "PreProcessResolver.h"
namespace Refactoring
{
RFTAPARSER_TEST_SUITE_REGISTRATION( PreProcessResolveTest );
PreProcessResolveTest::PreProcessResolveTest()
{
}
PreProcessResolveTest::~PreProcessResolveTest()
{
}
void
PreProcessResolveTest::setUp()
{
}
void
PreProcessResolveTest::tearDown()
{
}
void
PreProcessResolveTest::testMacroRegister()
{
PreProcessResolver resolver;
std::string source( "#define MY \"this text\"\n");
resolver.parseDirective(source.c_str(),source.c_str()+source.size());
CPPUNIT_ASSERT( resolver.isMacroIdentifier("MY") );
CPPUNIT_ASSERT_EQUAL( resolver.getMacroReplacement("MY") , std::string("\"this text\"") );
}
void
PreProcessResolveTest::testIncludeRegister()
{
}
} // namespace Refactoring
--- NEW FILE: PreProcessResolverTest.h ---
// //////////////////////////////////////////////////////////////////////////
// Header file PreProcessResolveTest.h for class PreProcessResolveTest
// (c)Copyright 2003, Andre Baresel
// Created: 2003/12/13
// //////////////////////////////////////////////////////////////////////////
#ifndef RFTA_PREPROCESSRESOLVETEST_H
#define RFTA_PREPROCESSRESOLVETEST_H
#include "ParserTesting.h"
namespace Refactoring
{
/// Unit tests for PreProcessor
class PreProcessResolveTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( PreProcessResolveTest );
CPPUNIT_TEST( testMacroRegister );
CPPUNIT_TEST( testIncludeRegister );
CPPUNIT_TEST_SUITE_END();
public:
/*! Constructs a PreProcessResolveTest object.
*/
PreProcessResolveTest();
/// Destructor.
virtual ~PreProcessResolveTest();
void setUp();
void tearDown();
void testMacroRegister();
void testIncludeRegister();
private:
/// Prevents the use of the copy constructor.
PreProcessResolveTest( const PreProcessResolveTest &other );
/// Prevents the use of the copy operator.
void operator =( const PreProcessResolveTest &other );
private:
};
// Inlines methods for PreProcessResolveTest:
// ----------------------------------------
} // namespace Refactoring
#endif // RFTA_PREPROCESSRESOLVETEST_H
|