You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdevelop/lib/antlr/src/TokenStreamRewriteEngine.cpp

215 lines
5.6 KiB

#include <antlr/config.h>
#include <string>
#include <list>
#include <vector>
#include <map>
#include <utility>
#include <iostream>
#include <iterator>
#include <sstream>
#include <cassert>
#include <antlr/TokenStream.h>
#include <antlr/TokenWithIndex.h>
#include <antlr/BitSet.h>
#include <antlr/TokenStreamRewriteEngine.h>
#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
namespace antlr {
#endif
#ifndef NO_STATIC_CONSTS
const size_t TokenStreamRewriteEngine::MIN_TOKEN_INDEX = 0;
const int TokenStreamRewriteEngine::PROGRAM_INIT_SIZE = 100;
#endif
const char* TokenStreamRewriteEngine::DEFAULT_PROGRAM_NAME = "default";
namespace {
struct compareOperationIndex {
typedef TokenStreamRewriteEngine::RewriteOperation RewriteOperation;
bool operator() ( const RewriteOperation* a, const RewriteOperation* b ) const
{
return a->getIndex() < b->getIndex();
}
};
struct dumpTokenWithIndex {
dumpTokenWithIndex( ANTLR_USE_NAMESPACE(std)ostream& o ) : out(o) {}
void operator() ( const RefTokenWithIndex& t ) {
out << "[txt='" << t->getText() << "' tp=" << t->getType() << " idx=" << t->getIndex() << "]\n";
}
ANTLR_USE_NAMESPACE(std)ostream& out;
};
}
TokenStreamRewriteEngine::TokenStreamRewriteEngine(TokenStream& upstream)
: stream(upstream)
, index(MIN_TOKEN_INDEX)
, tokens()
, programs()
, discardMask()
{
}
TokenStreamRewriteEngine::TokenStreamRewriteEngine(TokenStream& upstream, size_t initialSize )
: stream(upstream)
, index(MIN_TOKEN_INDEX)
, tokens(initialSize)
, programs()
, discardMask()
{
}
RefToken TokenStreamRewriteEngine::nextToken( void )
{
RefTokenWithIndex t;
// suck tokens until end of stream or we find a non-discarded token
do {
t = RefTokenWithIndex(stream.nextToken());
if ( t )
{
t->setIndex(index); // what is t's index in list?
if ( t->getType() != Token::EOF_TYPE ) {
tokens.push_back(t); // track all tokens except EOF
}
index++; // move to next position
}
} while ( t && discardMask.member(t->getType()) );
return RefToken(t);
}
void TokenStreamRewriteEngine::rollback( const std::string& programName,
size_t instructionIndex )
{
program_map::iterator rewrite = programs.find(programName);
if( rewrite != programs.end() )
{
operation_list& prog = rewrite->second;
operation_list::iterator
j = prog.begin(),
end = prog.end();
std::advance(j,instructionIndex);
if( j != end )
prog.erase(j, end);
}
}
void TokenStreamRewriteEngine::originalToStream( std::ostream& out,
size_t start,
size_t end ) const
{
token_list::const_iterator s = tokens.begin();
std::advance( s, start );
token_list::const_iterator e = s;
std::advance( e, end-start );
std::for_each( s, e, tokenToStream(out) );
}
void TokenStreamRewriteEngine::toStream( std::ostream& out,
const std::string& programName,
size_t firstToken,
size_t lastToken ) const
{
if( tokens.size() == 0 )
return;
program_map::const_iterator rewriter = programs.find(programName);
if ( rewriter == programs.end() )
return;
// get the prog and some iterators in it...
const operation_list& prog = rewriter->second;
operation_list::const_iterator
rewriteOpIndex = prog.begin(),
rewriteOpEnd = prog.end();
size_t tokenCursor = firstToken;
// make sure we don't run out of the tokens we have...
if( lastToken > (tokens.size() - 1) )
lastToken = tokens.size() - 1;
while ( tokenCursor <= lastToken )
{
// std::cout << "tokenCursor = " << tokenCursor << " first prog index = " << (*rewriteOpIndex)->getIndex() << std::endl;
if( rewriteOpIndex != rewriteOpEnd )
{
size_t up_to_here = std::min(lastToken,(*rewriteOpIndex)->getIndex());
while( tokenCursor < up_to_here )
out << tokens[tokenCursor++]->getText();
}
while ( rewriteOpIndex != rewriteOpEnd &&
tokenCursor == (*rewriteOpIndex)->getIndex() &&
tokenCursor <= lastToken )
{
tokenCursor = (*rewriteOpIndex)->execute(out);
++rewriteOpIndex;
}
if( tokenCursor <= lastToken )
out << tokens[tokenCursor++]->getText();
}
// std::cout << "Handling tail operations # left = " << std::distance(rewriteOpIndex,rewriteOpEnd) << std::endl;
// now see if there are operations (append) beyond last token index
std::for_each( rewriteOpIndex, rewriteOpEnd, executeOperation(out) );
rewriteOpIndex = rewriteOpEnd;
}
void TokenStreamRewriteEngine::toDebugStream( std::ostream& out,
size_t start,
size_t end ) const
{
token_list::const_iterator s = tokens.begin();
std::advance( s, start );
token_list::const_iterator e = s;
std::advance( e, end-start );
std::for_each( s, e, dumpTokenWithIndex(out) );
}
void TokenStreamRewriteEngine::addToSortedRewriteList( const std::string& programName,
RewriteOperation* op )
{
program_map::iterator rewrites = programs.find(programName);
// check if we got the program already..
if ( rewrites == programs.end() )
{
// no prog make a new one...
operation_list ops;
ops.push_back(op);
programs.insert(std::make_pair(programName,ops));
return;
}
operation_list& prog = rewrites->second;
if( prog.empty() )
{
prog.push_back(op);
return;
}
operation_list::iterator i, end = prog.end();
i = end;
--i;
// if at or beyond last op's index, just append
if ( op->getIndex() >= (*i)->getIndex() ) {
prog.push_back(op); // append to list of operations
return;
}
i = prog.begin();
if( i != end )
{
operation_list::iterator pos = std::upper_bound( i, end, op, compareOperationIndex() );
prog.insert(pos,op);
}
else
prog.push_back(op);
}
#ifdef ANTLR_CXX_SUPPORTS_NAMESPACE
}
#endif