Files
clang-p2996/clang/lib/Rewrite/TokenRewriter.cpp
Chris Lattner 5a7971e0c3 This change refactors some of the low-level lexer interfaces a bit.
Token now has a class of kinds for "literals", which include 
numeric constants, strings, etc.  These tokens can optionally have
a pointer to the start of the token in the lexer buffer.  This 
makes it faster to get spelling and do other gymnastics, because we
don't have to go through source locations.

This change is performance neutral, but will make other changes
more feasible down the road.

llvm-svn: 63028
2009-01-26 19:29:26 +00:00

99 lines
3.0 KiB
C++

//===--- TokenRewriter.cpp - Token-based code rewriting interface ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TokenRewriter class, which is used for code
// transformations.
//
//===----------------------------------------------------------------------===//
#include "clang/Rewrite/TokenRewriter.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/ScratchBuffer.h"
#include "clang/Basic/SourceManager.h"
using namespace clang;
TokenRewriter::TokenRewriter(FileID FID, SourceManager &SM,
const LangOptions &LangOpts) {
ScratchBuf.reset(new ScratchBuffer(SM));
// Create a lexer to lex all the tokens of the main file in raw mode.
Lexer RawLex(FID, SM, LangOpts);
// Return all comments and whitespace as tokens.
RawLex.SetKeepWhitespaceMode(true);
// Lex the file, populating our datastructures.
Token RawTok;
RawLex.LexFromRawLexer(RawTok);
while (RawTok.isNot(tok::eof)) {
#if 0
if (Tok.is(tok::identifier)) {
// Look up the identifier info for the token. This should use
// IdentifierTable directly instead of PP.
Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
}
#endif
AddToken(RawTok, TokenList.end());
RawLex.LexFromRawLexer(RawTok);
}
}
TokenRewriter::~TokenRewriter() {
}
/// RemapIterator - Convert from token_iterator (a const iterator) to
/// TokenRefTy (a non-const iterator).
TokenRewriter::TokenRefTy TokenRewriter::RemapIterator(token_iterator I) {
if (I == token_end()) return TokenList.end();
// FIXME: This is horrible, we should use our own list or something to avoid
// this.
std::map<SourceLocation, TokenRefTy>::iterator MapIt =
TokenAtLoc.find(I->getLocation());
assert(MapIt != TokenAtLoc.end() && "iterator not in rewriter?");
return MapIt->second;
}
/// AddToken - Add the specified token into the Rewriter before the other
/// position.
TokenRewriter::TokenRefTy
TokenRewriter::AddToken(const Token &T, TokenRefTy Where) {
Where = TokenList.insert(Where, T);
bool InsertSuccess = TokenAtLoc.insert(std::make_pair(T.getLocation(),
Where)).second;
assert(InsertSuccess && "Token location already in rewriter!");
InsertSuccess = InsertSuccess;
return Where;
}
TokenRewriter::token_iterator
TokenRewriter::AddTokenBefore(token_iterator I, const char *Val) {
unsigned Len = strlen(Val);
// Plop the string into the scratch buffer, then create a token for this
// string.
Token Tok;
Tok.startToken();
const char *Spelling;
Tok.setLocation(ScratchBuf->getToken(Val, Len, Spelling));
Tok.setLength(Len);
// TODO: Form a whole lexer around this and relex the token! For now, just
// set kind to tok::unknown.
Tok.setKind(tok::unknown);
return AddToken(Tok, RemapIterator(I));
}