]> granicus.if.org Git - clang/commitdiff
Add Preprocessor::LookNext method, which implements an efficient way to 'take a peek...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 9 Jul 2008 22:46:46 +0000 (22:46 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 9 Jul 2008 22:46:46 +0000 (22:46 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53375 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Lex/Preprocessor.h
lib/Lex/PPLexerChange.cpp

index 2617f2838bc31a987044acd8822dbd17e2b71a20..01d88d1e90de802d6288492bccddc2f663ceb6db 100644 (file)
@@ -138,6 +138,11 @@ class Preprocessor {
   enum { TokenLexerCacheSize = 8 };
   unsigned NumCachedTokenLexers;
   TokenLexer *TokenLexerCache[TokenLexerCacheSize];
+
+  /// PeekedToken - Cache the token that was retrieved through LookNext().
+  /// This is a valid token (its Location is valid) when LookNext() is
+  /// called and gets invalid again when it is "consumed" by Lex().
+  Token PeekedToken;
 public:
   Preprocessor(Diagnostic &diags, const LangOptions &opts, TargetInfo &target,
                SourceManager &SM, HeaderSearch &Headers);
@@ -258,8 +263,13 @@ public:
   void Lex(Token &Result) {
     if (CurLexer)
       CurLexer->Lex(Result);
-    else
+    else if (CurTokenLexer)
       CurTokenLexer->Lex(Result);
+    else {
+      // We have a peeked token that hasn't been consumed yet.
+      Result = PeekedToken;
+      ConsumedPeekedToken();
+    }
   }
   
   /// LexNonComment - Lex a token.  If it's a comment, keep lexing until we get
@@ -294,6 +304,27 @@ public:
   /// code paths if possible!
   ///
   Token LookAhead(unsigned N);
+
+  /// LookNext - Returns the next token that would be returned by Lex() without
+  /// consuming it.
+  const Token &LookNext() {
+    if (PeekedToken.getLocation().isInvalid()) {
+      // We don't have a peeked token that hasn't been consumed yet.
+      // Peek it now.
+      PeekToken();
+    }
+    return PeekedToken;
+  }
+
+private:
+  /// PeekToken - Lexes one token into PeekedToken and pushes CurLexer,
+  /// CurLexerToken into the IncludeMacroStack before setting them to null.
+  void PeekToken();
+
+  /// ConsumedPeekedToken - Called when Lex() is about to return the PeekedToken
+  /// and have it "consumed".
+  void ConsumedPeekedToken();
+public:
   
   /// Diag - Forwarding function for diagnostics.  This emits a diagnostic at
   /// the specified Token's location, translating the token's start
index c15675114d314cf0d207b31d8461e824c3c6dfe0..bef522e346af230ef099d202ae1845a39c35671a 100644 (file)
@@ -85,6 +85,10 @@ Token Preprocessor::LookAhead(unsigned N) {
   // size we new to a multiple of 16 tokens.  If the previous buffer has space
   // left, we can just grow it.  This means we only have to do the new 1/16th as
   // often.
+
+  // Optimized LookAhead(0) case.
+  if (N == 0)
+    return LookNext();
   
   Token *LookaheadTokens = new Token[N+1];
 
@@ -122,6 +126,28 @@ Token Preprocessor::LookAhead(unsigned N) {
   return Tok;
 }
 
+/// PeekToken - Lexes one token into PeekedToken and pushes CurLexer,\r
+/// CurLexerToken into the IncludeMacroStack before setting them to null.\r
+void Preprocessor::PeekToken() {\r
+  Lex(PeekedToken);\r
+  // Cache the current Lexer, TokenLexer and set them both to null.\r
+  // When Lex() is called, PeekedToken will be "consumed".\r
+  IncludeMacroStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup,\r
+                                               CurTokenLexer));\r
+  CurLexer = 0;\r
+  CurTokenLexer = 0;\r
+}\r
+
+/// ConsumedPeekedToken - Called when Lex() is about to return the PeekedToken\r
+/// and have it "consumed".\r
+void Preprocessor::ConsumedPeekedToken() {\r
+  assert(PeekedToken.getLocation().isValid() && "Confused Peeking?");\r
+  // Restore CurLexer, TokenLexer.\r
+  RemoveTopOfLexerStack();\r
+  // Make PeekedToken invalid.\r
+  PeekedToken.startToken();\r
+}\r
+
 
 //===----------------------------------------------------------------------===//
 // Methods for Entering and Callbacks for leaving various contexts