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/TokenRewriter.h" 16 #include "clang/Lex/Lexer.h" 17 #include "clang/Lex/ScratchBuffer.h" 18 #include "clang/Basic/SourceManager.h" 19 using namespace clang; 20 21 TokenRewriter::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 Lexer RawLex(FID, SM, LangOpts); 27 28 // Return all comments and whitespace as tokens. 29 RawLex.SetKeepWhitespaceMode(true); 30 31 // Lex the file, populating our datastructures. 32 Token RawTok; 33 RawLex.LexFromRawLexer(RawTok); 34 while (RawTok.isNot(tok::eof)) { 35 #if 0 36 if (Tok.is(tok::identifier)) { 37 // Look up the identifier info for the token. This should use 38 // IdentifierTable directly instead of PP. 39 Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok)); 40 } 41 #endif 42 43 AddToken(RawTok, TokenList.end()); 44 RawLex.LexFromRawLexer(RawTok); 45 } 46 } 47 48 TokenRewriter::~TokenRewriter() { 49 } 50 51 52 /// RemapIterator - Convert from token_iterator (a const iterator) to 53 /// TokenRefTy (a non-const iterator). 54 TokenRewriter::TokenRefTy TokenRewriter::RemapIterator(token_iterator I) { 55 if (I == token_end()) return TokenList.end(); 56 57 // FIXME: This is horrible, we should use our own list or something to avoid 58 // this. 59 std::map<SourceLocation, TokenRefTy>::iterator MapIt = 60 TokenAtLoc.find(I->getLocation()); 61 assert(MapIt != TokenAtLoc.end() && "iterator not in rewriter?"); 62 return MapIt->second; 63 } 64 65 66 /// AddToken - Add the specified token into the Rewriter before the other 67 /// position. 68 TokenRewriter::TokenRefTy 69 TokenRewriter::AddToken(const Token &T, TokenRefTy Where) { 70 Where = TokenList.insert(Where, T); 71 72 bool InsertSuccess = TokenAtLoc.insert(std::make_pair(T.getLocation(), 73 Where)).second; 74 assert(InsertSuccess && "Token location already in rewriter!"); 75 InsertSuccess = InsertSuccess; 76 return Where; 77 } 78 79 80 TokenRewriter::token_iterator 81 TokenRewriter::AddTokenBefore(token_iterator I, const char *Val) { 82 unsigned Len = strlen(Val); 83 84 // Plop the string into the scratch buffer, then create a token for this 85 // string. 86 Token Tok; 87 Tok.startToken(); 88 const char *Spelling; 89 Tok.setLocation(ScratchBuf->getToken(Val, Len, Spelling)); 90 Tok.setLength(Len); 91 92 // TODO: Form a whole lexer around this and relex the token! For now, just 93 // set kind to tok::unknown. 94 Tok.setKind(tok::unknown); 95 96 return AddToken(Tok, RemapIterator(I)); 97 } 98 99