blob: 20e3b3dd9d8e7bb55e9be064f6e48d51aa57fec9 [file] [log] [blame]
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +00001//===--- 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"
16using namespace clang;
17
Argyrios Kyrtzidis91c3f522008-09-05 08:53:53 +000018/// 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.
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000026void Preprocessor::EnableBacktrackAtThisPos() {
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000027 BacktrackPositions.push_back(CachedLexPos);
28 EnterCachingLexMode();
29}
Argyrios Kyrtzidisa65490c2008-08-22 21:27:50 +000030
Argyrios Kyrtzidis75b34532008-08-24 12:29:43 +000031/// CommitBacktrackedTokens - Disable the last EnableBacktrackAtThisPos call.
32void Preprocessor::CommitBacktrackedTokens() {
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000033 assert(!BacktrackPositions.empty()
34 && "EnableBacktrackAtThisPos was not called!");
35 BacktrackPositions.pop_back();
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000036}
37
38/// Backtrack - Make Preprocessor re-lex the tokens that were lexed since
Mike Stump11289f42009-09-09 15:08:12 +000039/// EnableBacktrackAtThisPos() was previously called.
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000040void Preprocessor::Backtrack() {
41 assert(!BacktrackPositions.empty()
42 && "EnableBacktrackAtThisPos was not called!");
43 CachedLexPos = BacktrackPositions.back();
44 BacktrackPositions.pop_back();
Argyrios Kyrtzidisbd024c72008-08-23 12:05:53 +000045}
Argyrios Kyrtzidisa65490c2008-08-22 21:27:50 +000046
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000047void Preprocessor::CachingLex(Token &Result) {
48 if (CachedLexPos < CachedTokens.size()) {
49 Result = CachedTokens[CachedLexPos++];
50 return;
51 }
52
53 ExitCachingLexMode();
54 Lex(Result);
55
Argyrios Kyrtzidisf5e28122008-11-19 14:23:14 +000056 if (!isBacktrackEnabled()) {
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000057 // All cached tokens were consumed.
58 CachedTokens.clear();
59 CachedLexPos = 0;
60 return;
61 }
62
Chris Lattner5a503e92010-07-12 04:25:32 +000063 // Cache the lexed token.
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000064 EnterCachingLexMode();
Chris Lattner5a503e92010-07-12 04:25:32 +000065 CachedTokens.push_back(Result);
66 ++CachedLexPos;
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000067}
68
69void Preprocessor::EnterCachingLexMode() {
70 if (InCachingLexMode())
71 return;
72
Ted Kremenek50b4f482008-11-12 22:21:57 +000073 PushIncludeMacroStack();
Argyrios Kyrtzidisb3dd1e02008-08-10 13:15:22 +000074}
75
76
77const Token &Preprocessor::PeekAhead(unsigned N) {
78 assert(CachedLexPos + N > CachedTokens.size() && "Confused caching.");
79 ExitCachingLexMode();
80 for (unsigned C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) {
81 CachedTokens.push_back(Token());
82 Lex(CachedTokens.back());
83 }
84 EnterCachingLexMode();
85 return CachedTokens.back();
86}
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +000087
88void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) {
Chris Lattner5a7971e2009-01-26 19:29:26 +000089 assert(Tok.isAnnotation() && "Expected annotation token");
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +000090 assert(CachedLexPos != 0 && "Expected to have some cached tokens");
Sebastian Redlb0e3e1b2010-02-08 19:35:18 +000091 assert(CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc()
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +000092 && "The annotation should be until the most recent cached token");
93
94 // Start from the end of the cached tokens list and look for the token
95 // that is the beginning of the annotation token.
96 for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) {
97 CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1;
98 if (AnnotBegin->getLocation() == Tok.getLocation()) {
99 assert((BacktrackPositions.empty() || BacktrackPositions.back() < i) &&
100 "The backtrack pos points inside the annotated tokens!");
101 // Replace the cached tokens with the single annotation token.
Nuno Lopesbd2cd922009-07-26 16:36:45 +0000102 if (i < CachedLexPos)
103 CachedTokens.erase(AnnotBegin + 1, CachedTokens.begin() + CachedLexPos);
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +0000104 *AnnotBegin = Tok;
105 CachedLexPos = i;
106 return;
107 }
108 }
Argyrios Kyrtzidisc7e67a04c2008-11-08 16:17:04 +0000109}