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