PreprocessorLexer.h revision 809d1be9820039b4cf6efa48246a0d70ffa13394
1//===--- PreprocessorLexer.h - C Language Family Lexer ----------*- C++ -*-===//
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 defines the PreprocessorLexer interface.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_PreprocessorLexer_H
15#define LLVM_CLANG_PreprocessorLexer_H
16
17#include "clang/Lex/MultipleIncludeOpt.h"
18#include "clang/Lex/Token.h"
19#include "llvm/ADT/SmallVector.h"
20
21namespace clang {
22
23class FileEntry;
24class Preprocessor;
25
26class PreprocessorLexer {
27  virtual void anchor();
28protected:
29  Preprocessor *PP;              // Preprocessor object controlling lexing.
30
31  /// The SourceManager FileID corresponding to the file being lexed.
32  const FileID FID;
33
34  /// \brief Number of SLocEntries before lexing the file.
35  unsigned InitialNumSLocEntries;
36
37  //===--------------------------------------------------------------------===//
38  // Context-specific lexing flags set by the preprocessor.
39  //===--------------------------------------------------------------------===//
40
41  /// ParsingPreprocessorDirective - This is true when parsing #XXX.  This turns
42  /// '\n' into a tok::eod token.
43  bool ParsingPreprocessorDirective;
44
45  /// ParsingFilename - True after #include: this turns <xx> into a
46  /// tok::angle_string_literal token.
47  bool ParsingFilename;
48
49  /// LexingRawMode - True if in raw mode:  This flag disables interpretation of
50  /// tokens and is a far faster mode to lex in than non-raw-mode.  This flag:
51  ///  1. If EOF of the current lexer is found, the include stack isn't popped.
52  ///  2. Identifier information is not looked up for identifier tokens.  As an
53  ///     effect of this, implicit macro expansion is naturally disabled.
54  ///  3. "#" tokens at the start of a line are treated as normal tokens, not
55  ///     implicitly transformed by the lexer.
56  ///  4. All diagnostic messages are disabled.
57  ///  5. No callbacks are made into the preprocessor.
58  ///
59  /// Note that in raw mode that the PP pointer may be null.
60  bool LexingRawMode;
61
62  /// MIOpt - This is a state machine that detects the #ifndef-wrapping a file
63  /// idiom for the multiple-include optimization.
64  MultipleIncludeOpt MIOpt;
65
66  /// ConditionalStack - Information about the set of #if/#ifdef/#ifndef blocks
67  /// we are currently in.
68  SmallVector<PPConditionalInfo, 4> ConditionalStack;
69
70  PreprocessorLexer(const PreprocessorLexer&);          // DO NOT IMPLEMENT
71  void operator=(const PreprocessorLexer&); // DO NOT IMPLEMENT
72  friend class Preprocessor;
73
74  PreprocessorLexer(Preprocessor *pp, FileID fid);
75
76  PreprocessorLexer()
77    : PP(0), InitialNumSLocEntries(0),
78      ParsingPreprocessorDirective(false),
79      ParsingFilename(false),
80      LexingRawMode(false) {}
81
82  virtual ~PreprocessorLexer() {}
83
84  virtual void IndirectLex(Token& Result) = 0;
85
86  /// getSourceLocation - Return the source location for the next observable
87  ///  location.
88  virtual SourceLocation getSourceLocation() = 0;
89
90  //===--------------------------------------------------------------------===//
91  // #if directive handling.
92
93  /// pushConditionalLevel - When we enter a #if directive, this keeps track of
94  /// what we are currently in for diagnostic emission (e.g. #if with missing
95  /// #endif).
96  void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping,
97                            bool FoundNonSkip, bool FoundElse) {
98    PPConditionalInfo CI;
99    CI.IfLoc = DirectiveStart;
100    CI.WasSkipping = WasSkipping;
101    CI.FoundNonSkip = FoundNonSkip;
102    CI.FoundElse = FoundElse;
103    ConditionalStack.push_back(CI);
104  }
105  void pushConditionalLevel(const PPConditionalInfo &CI) {
106    ConditionalStack.push_back(CI);
107  }
108
109  /// popConditionalLevel - Remove an entry off the top of the conditional
110  /// stack, returning information about it.  If the conditional stack is empty,
111  /// this returns true and does not fill in the arguments.
112  bool popConditionalLevel(PPConditionalInfo &CI) {
113    if (ConditionalStack.empty()) return true;
114    CI = ConditionalStack.back();
115    ConditionalStack.pop_back();
116    return false;
117  }
118
119  /// peekConditionalLevel - Return the top of the conditional stack.  This
120  /// requires that there be a conditional active.
121  PPConditionalInfo &peekConditionalLevel() {
122    assert(!ConditionalStack.empty() && "No conditionals active!");
123    return ConditionalStack.back();
124  }
125
126  unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
127
128public:
129
130  //===--------------------------------------------------------------------===//
131  // Misc. lexing methods.
132
133  /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
134  /// (potentially) macro expand the filename.  If the sequence parsed is not
135  /// lexically legal, emit a diagnostic and return a result EOD token.
136  void LexIncludeFilename(Token &Result);
137
138  /// setParsingPreprocessorDirective - Inform the lexer whether or not
139  ///  we are currently lexing a preprocessor directive.
140  void setParsingPreprocessorDirective(bool f) {
141    ParsingPreprocessorDirective = f;
142  }
143
144  /// isLexingRawMode - Return true if this lexer is in raw mode or not.
145  bool isLexingRawMode() const { return LexingRawMode; }
146
147  /// getPP - Return the preprocessor object for this lexer.
148  Preprocessor *getPP() const { return PP; }
149
150  FileID getFileID() const {
151    assert(PP &&
152      "PreprocessorLexer::getFileID() should only be used with a Preprocessor");
153    return FID;
154  }
155
156  /// \brief Number of SLocEntries before lexing the file.
157  unsigned getInitialNumSLocEntries() const {
158    return InitialNumSLocEntries;
159  }
160
161  /// getFileEntry - Return the FileEntry corresponding to this FileID.  Like
162  /// getFileID(), this only works for lexers with attached preprocessors.
163  const FileEntry *getFileEntry() const;
164
165  /// \brief Iterator that traverses the current stack of preprocessor
166  /// conditional directives (\#if/\#ifdef/\#ifndef).
167  typedef SmallVectorImpl<PPConditionalInfo>::const_iterator
168    conditional_iterator;
169
170  conditional_iterator conditional_begin() const {
171    return ConditionalStack.begin();
172  }
173  conditional_iterator conditional_end() const {
174    return ConditionalStack.end();
175  }
176};
177
178}  // end namespace clang
179
180#endif
181