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   recomputeCurLexerKind();
     46 }
     47 
     48 void Preprocessor::CachingLex(Token &Result) {
     49   if (!InCachingLexMode())
     50     return;
     51 
     52   if (CachedLexPos < CachedTokens.size()) {
     53     Result = CachedTokens[CachedLexPos++];
     54     return;
     55   }
     56 
     57   ExitCachingLexMode();
     58   Lex(Result);
     59 
     60   if (isBacktrackEnabled()) {
     61     // Cache the lexed token.
     62     EnterCachingLexMode();
     63     CachedTokens.push_back(Result);
     64     ++CachedLexPos;
     65     return;
     66   }
     67 
     68   if (CachedLexPos < CachedTokens.size()) {
     69     EnterCachingLexMode();
     70   } else {
     71     // All cached tokens were consumed.
     72     CachedTokens.clear();
     73     CachedLexPos = 0;
     74   }
     75 }
     76 
     77 void Preprocessor::EnterCachingLexMode() {
     78   if (InCachingLexMode())
     79     return;
     80 
     81   PushIncludeMacroStack();
     82   CurLexerKind = CLK_CachingLexer;
     83 }
     84 
     85 
     86 const Token &Preprocessor::PeekAhead(unsigned N) {
     87   assert(CachedLexPos + N > CachedTokens.size() && "Confused caching.");
     88   ExitCachingLexMode();
     89   for (unsigned C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) {
     90     CachedTokens.push_back(Token());
     91     Lex(CachedTokens.back());
     92   }
     93   EnterCachingLexMode();
     94   return CachedTokens.back();
     95 }
     96 
     97 void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) {
     98   assert(Tok.isAnnotation() && "Expected annotation token");
     99   assert(CachedLexPos != 0 && "Expected to have some cached tokens");
    100   assert(CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc()
    101          && "The annotation should be until the most recent cached token");
    102 
    103   // Start from the end of the cached tokens list and look for the token
    104   // that is the beginning of the annotation token.
    105   for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) {
    106     CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1;
    107     if (AnnotBegin->getLocation() == Tok.getLocation()) {
    108       assert((BacktrackPositions.empty() || BacktrackPositions.back() < i) &&
    109              "The backtrack pos points inside the annotated tokens!");
    110       // Replace the cached tokens with the single annotation token.
    111       if (i < CachedLexPos)
    112         CachedTokens.erase(AnnotBegin + 1, CachedTokens.begin() + CachedLexPos);
    113       *AnnotBegin = Tok;
    114       CachedLexPos = i;
    115       return;
    116     }
    117   }
    118 }
    119