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 virtual void anchor(); 28 protected: 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 PreprocessorLexer()76 PreprocessorLexer() 77 : PP(0), InitialNumSLocEntries(0), 78 ParsingPreprocessorDirective(false), 79 ParsingFilename(false), 80 LexingRawMode(false) {} 81 ~PreprocessorLexer()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). pushConditionalLevel(SourceLocation DirectiveStart,bool WasSkipping,bool FoundNonSkip,bool FoundElse)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 } pushConditionalLevel(const PPConditionalInfo & CI)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. popConditionalLevel(PPConditionalInfo & CI)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. peekConditionalLevel()121 PPConditionalInfo &peekConditionalLevel() { 122 assert(!ConditionalStack.empty() && "No conditionals active!"); 123 return ConditionalStack.back(); 124 } 125 getConditionalStackDepth()126 unsigned getConditionalStackDepth() const { return ConditionalStack.size(); } 127 128 public: 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. setParsingPreprocessorDirective(bool f)140 void setParsingPreprocessorDirective(bool f) { 141 ParsingPreprocessorDirective = f; 142 } 143 144 /// isLexingRawMode - Return true if this lexer is in raw mode or not. isLexingRawMode()145 bool isLexingRawMode() const { return LexingRawMode; } 146 147 /// getPP - Return the preprocessor object for this lexer. getPP()148 Preprocessor *getPP() const { return PP; } 149 getFileID()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. getInitialNumSLocEntries()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 conditional_begin()170 conditional_iterator conditional_begin() const { 171 return ConditionalStack.begin(); 172 } conditional_end()173 conditional_iterator conditional_end() const { 174 return ConditionalStack.end(); 175 } 176 }; 177 178 } // end namespace clang 179 180 #endif 181