PTHLexer.cpp revision cd4e2aecde5bb7810715d5d5a88ac63ce7946f34
1//===--- PTHLexer.cpp - Lex from a token stream ---------------------------===//
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 the PTHLexer interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Lex/PTHLexer.h"
15#include "clang/Lex/Preprocessor.h"
16#include "clang/Basic/TokenKinds.h"
17using namespace clang;
18
19PTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc,
20                   const Token *TokArray, unsigned NumTokens)
21  : PreprocessorLexer(&pp, fileloc),
22    Tokens(TokArray),
23    LastTokenIdx(NumTokens - 1),
24    CurTokenIdx(0) {
25
26  assert(NumTokens >= 1);
27  assert(Tokens[LastTokenIdx].is(tok::eof));
28}
29
30Token PTHLexer::GetToken() {
31  Token Tok = Tokens[CurTokenIdx];
32
33  // If we are in raw mode, zero out identifier pointers.  This is
34  // needed for 'pragma poison'.  Note that this requires that the Preprocessor
35  // can go back to the original source when it calls getSpelling().
36  if (LexingRawMode && Tok.is(tok::identifier))
37    Tok.setIdentifierInfo(0);
38
39  return Tok;
40}
41
42void PTHLexer::Lex(Token& Tok) {
43LexNextToken:
44  Tok = GetToken();
45
46  if (AtLastToken()) {
47    Preprocessor *PPCache = PP;
48
49    if (LexEndOfFile(Tok))
50      return;
51
52    assert(PPCache && "Raw buffer::LexEndOfFile should return a token");
53    return PPCache->Lex(Tok);
54  }
55
56  // Don't advance to the next token yet.  Check if we are at the
57  // start of a new line and we're processing a directive.  If so, we
58  // consume this token twice, once as an tok::eom.
59  if (Tok.isAtStartOfLine() && ParsingPreprocessorDirective) {
60    ParsingPreprocessorDirective = false;
61    Tok.setKind(tok::eom);
62    MIOpt.ReadToken();
63    return;
64  }
65
66  // Advance to the next token.
67  AdvanceToken();
68
69  if (Tok.is(tok::hash)) {
70    if (Tok.isAtStartOfLine() && !LexingRawMode) {
71      PP->HandleDirective(Tok);
72
73      if (PP->isCurrentLexer(this))
74        goto LexNextToken;
75
76      return PP->Lex(Tok);
77    }
78  }
79
80  MIOpt.ReadToken();
81
82  if (Tok.is(tok::identifier)) {
83    if (LexingRawMode) return;
84    return PP->HandleIdentifier(Tok);
85  }
86}
87
88bool PTHLexer::LexEndOfFile(Token &Tok) {
89
90  if (ParsingPreprocessorDirective) {
91    ParsingPreprocessorDirective = false;
92    Tok.setKind(tok::eom);
93    MIOpt.ReadToken();
94    return true; // Have a token.
95  }
96
97  if (LexingRawMode) {
98    MIOpt.ReadToken();
99    return true;  // Have an eof token.
100  }
101
102  // FIXME: Issue diagnostics similar to Lexer.
103  return PP->HandleEndOfFile(Tok, false);
104}
105
106void PTHLexer::setEOF(Token& Tok) {
107  Tok = Tokens[LastTokenIdx];
108}
109
110void PTHLexer::DiscardToEndOfLine() {
111  assert(ParsingPreprocessorDirective && ParsingFilename == false &&
112         "Must be in a preprocessing directive!");
113
114  // Already at end-of-file?
115  if (AtLastToken())
116    return;
117
118  // Find the first token that is not the start of the *current* line.
119  for (AdvanceToken(); !AtLastToken(); AdvanceToken())
120    if (GetToken().isAtStartOfLine())
121      return;
122}
123