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