1163533Simp//===--- PPCaching.cpp - Handle caching lexed tokens ----------------------===//
2163533Simp//
3163533Simp//                     The LLVM Compiler Infrastructure
4163533Simp//
5163533Simp// This file is distributed under the University of Illinois Open Source
6163533Simp// License. See LICENSE.TXT for details.
7163533Simp//
8163533Simp//===----------------------------------------------------------------------===//
9163533Simp//
10163533Simp// This file implements pieces of the Preprocessor interface that manage the
11163533Simp// caching of lexed tokens.
12163533Simp//
13163533Simp//===----------------------------------------------------------------------===//
14163533Simp
15163533Simp#include "clang/Lex/Preprocessor.h"
16163533Simpusing namespace clang;
17163533Simp
18163533Simp/// EnableBacktrackAtThisPos - From the point that this method is called, and
19163533Simp/// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
20163533Simp/// keeps track of the lexed tokens so that a subsequent Backtrack() call will
21163533Simp/// make the Preprocessor re-lex the same tokens.
22163533Simp///
23163533Simp/// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can
24163533Simp/// be called multiple times and CommitBacktrackedTokens/Backtrack calls will
25164137Simp/// be combined with the EnableBacktrackAtThisPos calls in reverse order.
26164137Simpvoid Preprocessor::EnableBacktrackAtThisPos() {
27164137Simp  BacktrackPositions.push_back(CachedLexPos);
28164137Simp  EnterCachingLexMode();
29163533Simp}
30163533Simp
31163533Simp/// CommitBacktrackedTokens - Disable the last EnableBacktrackAtThisPos call.
32163533Simpvoid Preprocessor::CommitBacktrackedTokens() {
33163533Simp  assert(!BacktrackPositions.empty()
34163533Simp         && "EnableBacktrackAtThisPos was not called!");
35163533Simp  BacktrackPositions.pop_back();
36163533Simp}
37
38/// Backtrack - Make Preprocessor re-lex the tokens that were lexed since
39/// EnableBacktrackAtThisPos() was previously called.
40void Preprocessor::Backtrack() {
41  assert(!BacktrackPositions.empty()
42         && "EnableBacktrackAtThisPos was not called!");
43  CachedLexPos = BacktrackPositions.back();
44  BacktrackPositions.pop_back();
45  recomputeCurLexerKind();
46}
47
48void 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
77void Preprocessor::EnterCachingLexMode() {
78  if (InCachingLexMode())
79    return;
80
81  PushIncludeMacroStack();
82  CurLexerKind = CLK_CachingLexer;
83}
84
85
86const 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
97void 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