1//===--- TokenRewriter.cpp - Token-based code rewriting interface ---------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the TokenRewriter class, which is used for code 11// transformations. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/Rewrite/Core/TokenRewriter.h" 16#include "clang/Basic/SourceManager.h" 17#include "clang/Lex/Lexer.h" 18#include "clang/Lex/ScratchBuffer.h" 19using namespace clang; 20 21TokenRewriter::TokenRewriter(FileID FID, SourceManager &SM, 22 const LangOptions &LangOpts) { 23 ScratchBuf.reset(new ScratchBuffer(SM)); 24 25 // Create a lexer to lex all the tokens of the main file in raw mode. 26 const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID); 27 Lexer RawLex(FID, FromFile, SM, LangOpts); 28 29 // Return all comments and whitespace as tokens. 30 RawLex.SetKeepWhitespaceMode(true); 31 32 // Lex the file, populating our datastructures. 33 Token RawTok; 34 RawLex.LexFromRawLexer(RawTok); 35 while (RawTok.isNot(tok::eof)) { 36#if 0 37 if (Tok.is(tok::raw_identifier)) { 38 // Look up the identifier info for the token. This should use 39 // IdentifierTable directly instead of PP. 40 PP.LookUpIdentifierInfo(Tok); 41 } 42#endif 43 44 AddToken(RawTok, TokenList.end()); 45 RawLex.LexFromRawLexer(RawTok); 46 } 47} 48 49TokenRewriter::~TokenRewriter() { 50} 51 52 53/// RemapIterator - Convert from token_iterator (a const iterator) to 54/// TokenRefTy (a non-const iterator). 55TokenRewriter::TokenRefTy TokenRewriter::RemapIterator(token_iterator I) { 56 if (I == token_end()) return TokenList.end(); 57 58 // FIXME: This is horrible, we should use our own list or something to avoid 59 // this. 60 std::map<SourceLocation, TokenRefTy>::iterator MapIt = 61 TokenAtLoc.find(I->getLocation()); 62 assert(MapIt != TokenAtLoc.end() && "iterator not in rewriter?"); 63 return MapIt->second; 64} 65 66 67/// AddToken - Add the specified token into the Rewriter before the other 68/// position. 69TokenRewriter::TokenRefTy 70TokenRewriter::AddToken(const Token &T, TokenRefTy Where) { 71 Where = TokenList.insert(Where, T); 72 73 bool InsertSuccess = TokenAtLoc.insert(std::make_pair(T.getLocation(), 74 Where)).second; 75 assert(InsertSuccess && "Token location already in rewriter!"); 76 (void)InsertSuccess; 77 return Where; 78} 79 80 81TokenRewriter::token_iterator 82TokenRewriter::AddTokenBefore(token_iterator I, const char *Val) { 83 unsigned Len = strlen(Val); 84 85 // Plop the string into the scratch buffer, then create a token for this 86 // string. 87 Token Tok; 88 Tok.startToken(); 89 const char *Spelling; 90 Tok.setLocation(ScratchBuf->getToken(Val, Len, Spelling)); 91 Tok.setLength(Len); 92 93 // TODO: Form a whole lexer around this and relex the token! For now, just 94 // set kind to tok::unknown. 95 Tok.setKind(tok::unknown); 96 97 return AddToken(Tok, RemapIterator(I)); 98} 99 100