1f4a2713aSLionel Sambuc //===--- PPCaching.cpp - Handle caching lexed tokens ----------------------===// 2f4a2713aSLionel Sambuc // 3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4f4a2713aSLionel Sambuc // 5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7f4a2713aSLionel Sambuc // 8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9f4a2713aSLionel Sambuc // 10f4a2713aSLionel Sambuc // This file implements pieces of the Preprocessor interface that manage the 11f4a2713aSLionel Sambuc // caching of lexed tokens. 12f4a2713aSLionel Sambuc // 13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 14f4a2713aSLionel Sambuc 15f4a2713aSLionel Sambuc #include "clang/Lex/Preprocessor.h" 16f4a2713aSLionel Sambuc using namespace clang; 17f4a2713aSLionel Sambuc 18*0a6a1f1dSLionel Sambuc // EnableBacktrackAtThisPos - From the point that this method is called, and 19*0a6a1f1dSLionel Sambuc // until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor 20*0a6a1f1dSLionel Sambuc // keeps track of the lexed tokens so that a subsequent Backtrack() call will 21*0a6a1f1dSLionel Sambuc // make the Preprocessor re-lex the same tokens. 22*0a6a1f1dSLionel Sambuc // 23*0a6a1f1dSLionel Sambuc // Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can 24*0a6a1f1dSLionel Sambuc // be called multiple times and CommitBacktrackedTokens/Backtrack calls will 25*0a6a1f1dSLionel Sambuc // be combined with the EnableBacktrackAtThisPos calls in reverse order. EnableBacktrackAtThisPos()26f4a2713aSLionel Sambucvoid Preprocessor::EnableBacktrackAtThisPos() { 27f4a2713aSLionel Sambuc BacktrackPositions.push_back(CachedLexPos); 28f4a2713aSLionel Sambuc EnterCachingLexMode(); 29f4a2713aSLionel Sambuc } 30f4a2713aSLionel Sambuc 31*0a6a1f1dSLionel Sambuc // Disable the last EnableBacktrackAtThisPos call. CommitBacktrackedTokens()32f4a2713aSLionel Sambucvoid Preprocessor::CommitBacktrackedTokens() { 33f4a2713aSLionel Sambuc assert(!BacktrackPositions.empty() 34f4a2713aSLionel Sambuc && "EnableBacktrackAtThisPos was not called!"); 35f4a2713aSLionel Sambuc BacktrackPositions.pop_back(); 36f4a2713aSLionel Sambuc } 37f4a2713aSLionel Sambuc 38*0a6a1f1dSLionel Sambuc // Make Preprocessor re-lex the tokens that were lexed since 39*0a6a1f1dSLionel Sambuc // EnableBacktrackAtThisPos() was previously called. Backtrack()40f4a2713aSLionel Sambucvoid Preprocessor::Backtrack() { 41f4a2713aSLionel Sambuc assert(!BacktrackPositions.empty() 42f4a2713aSLionel Sambuc && "EnableBacktrackAtThisPos was not called!"); 43f4a2713aSLionel Sambuc CachedLexPos = BacktrackPositions.back(); 44f4a2713aSLionel Sambuc BacktrackPositions.pop_back(); 45f4a2713aSLionel Sambuc recomputeCurLexerKind(); 46f4a2713aSLionel Sambuc } 47f4a2713aSLionel Sambuc CachingLex(Token & Result)48f4a2713aSLionel Sambucvoid Preprocessor::CachingLex(Token &Result) { 49f4a2713aSLionel Sambuc if (!InCachingLexMode()) 50f4a2713aSLionel Sambuc return; 51f4a2713aSLionel Sambuc 52f4a2713aSLionel Sambuc if (CachedLexPos < CachedTokens.size()) { 53f4a2713aSLionel Sambuc Result = CachedTokens[CachedLexPos++]; 54f4a2713aSLionel Sambuc return; 55f4a2713aSLionel Sambuc } 56f4a2713aSLionel Sambuc 57f4a2713aSLionel Sambuc ExitCachingLexMode(); 58f4a2713aSLionel Sambuc Lex(Result); 59f4a2713aSLionel Sambuc 60f4a2713aSLionel Sambuc if (isBacktrackEnabled()) { 61f4a2713aSLionel Sambuc // Cache the lexed token. 62f4a2713aSLionel Sambuc EnterCachingLexMode(); 63f4a2713aSLionel Sambuc CachedTokens.push_back(Result); 64f4a2713aSLionel Sambuc ++CachedLexPos; 65f4a2713aSLionel Sambuc return; 66f4a2713aSLionel Sambuc } 67f4a2713aSLionel Sambuc 68f4a2713aSLionel Sambuc if (CachedLexPos < CachedTokens.size()) { 69f4a2713aSLionel Sambuc EnterCachingLexMode(); 70f4a2713aSLionel Sambuc } else { 71f4a2713aSLionel Sambuc // All cached tokens were consumed. 72f4a2713aSLionel Sambuc CachedTokens.clear(); 73f4a2713aSLionel Sambuc CachedLexPos = 0; 74f4a2713aSLionel Sambuc } 75f4a2713aSLionel Sambuc } 76f4a2713aSLionel Sambuc EnterCachingLexMode()77f4a2713aSLionel Sambucvoid Preprocessor::EnterCachingLexMode() { 78f4a2713aSLionel Sambuc if (InCachingLexMode()) 79f4a2713aSLionel Sambuc return; 80f4a2713aSLionel Sambuc 81f4a2713aSLionel Sambuc PushIncludeMacroStack(); 82f4a2713aSLionel Sambuc CurLexerKind = CLK_CachingLexer; 83f4a2713aSLionel Sambuc } 84f4a2713aSLionel Sambuc 85f4a2713aSLionel Sambuc PeekAhead(unsigned N)86f4a2713aSLionel Sambucconst Token &Preprocessor::PeekAhead(unsigned N) { 87f4a2713aSLionel Sambuc assert(CachedLexPos + N > CachedTokens.size() && "Confused caching."); 88f4a2713aSLionel Sambuc ExitCachingLexMode(); 89f4a2713aSLionel Sambuc for (unsigned C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) { 90f4a2713aSLionel Sambuc CachedTokens.push_back(Token()); 91f4a2713aSLionel Sambuc Lex(CachedTokens.back()); 92f4a2713aSLionel Sambuc } 93f4a2713aSLionel Sambuc EnterCachingLexMode(); 94f4a2713aSLionel Sambuc return CachedTokens.back(); 95f4a2713aSLionel Sambuc } 96f4a2713aSLionel Sambuc AnnotatePreviousCachedTokens(const Token & Tok)97f4a2713aSLionel Sambucvoid Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) { 98f4a2713aSLionel Sambuc assert(Tok.isAnnotation() && "Expected annotation token"); 99f4a2713aSLionel Sambuc assert(CachedLexPos != 0 && "Expected to have some cached tokens"); 100f4a2713aSLionel Sambuc assert(CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc() 101f4a2713aSLionel Sambuc && "The annotation should be until the most recent cached token"); 102f4a2713aSLionel Sambuc 103f4a2713aSLionel Sambuc // Start from the end of the cached tokens list and look for the token 104f4a2713aSLionel Sambuc // that is the beginning of the annotation token. 105f4a2713aSLionel Sambuc for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) { 106f4a2713aSLionel Sambuc CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1; 107f4a2713aSLionel Sambuc if (AnnotBegin->getLocation() == Tok.getLocation()) { 108f4a2713aSLionel Sambuc assert((BacktrackPositions.empty() || BacktrackPositions.back() < i) && 109f4a2713aSLionel Sambuc "The backtrack pos points inside the annotated tokens!"); 110f4a2713aSLionel Sambuc // Replace the cached tokens with the single annotation token. 111f4a2713aSLionel Sambuc if (i < CachedLexPos) 112f4a2713aSLionel Sambuc CachedTokens.erase(AnnotBegin + 1, CachedTokens.begin() + CachedLexPos); 113f4a2713aSLionel Sambuc *AnnotBegin = Tok; 114f4a2713aSLionel Sambuc CachedLexPos = i; 115f4a2713aSLionel Sambuc return; 116f4a2713aSLionel Sambuc } 117f4a2713aSLionel Sambuc } 118f4a2713aSLionel Sambuc } 119