1 //===--- UnwrappedLineParser.h - Format C++ code ----------------*- 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 /// \file 11 /// \brief This file contains the declaration of the UnwrappedLineParser, 12 /// which turns a stream of tokens into UnwrappedLines. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_CLANG_FORMAT_UNWRAPPED_LINE_PARSER_H 17 #define LLVM_CLANG_FORMAT_UNWRAPPED_LINE_PARSER_H 18 19 #include "clang/Basic/IdentifierTable.h" 20 #include "clang/Format/Format.h" 21 #include "FormatToken.h" 22 #include <list> 23 24 namespace clang { 25 namespace format { 26 27 /// \brief An unwrapped line is a sequence of \c Token, that we would like to 28 /// put on a single line if there was no column limit. 29 /// 30 /// This is used as a main interface between the \c UnwrappedLineParser and the 31 /// \c UnwrappedLineFormatter. The key property is that changing the formatting 32 /// within an unwrapped line does not affect any other unwrapped lines. 33 struct UnwrappedLine { 34 UnwrappedLine() : Level(0), InPPDirective(false), MustBeDeclaration(false) { 35 } 36 37 // FIXME: Don't use std::list here. 38 /// \brief The \c Tokens comprising this \c UnwrappedLine. 39 std::list<FormatToken *> Tokens; 40 41 /// \brief The indent level of the \c UnwrappedLine. 42 unsigned Level; 43 44 /// \brief Whether this \c UnwrappedLine is part of a preprocessor directive. 45 bool InPPDirective; 46 47 bool MustBeDeclaration; 48 }; 49 50 class UnwrappedLineConsumer { 51 public: 52 virtual ~UnwrappedLineConsumer() { 53 } 54 virtual void consumeUnwrappedLine(const UnwrappedLine &Line) = 0; 55 }; 56 57 class FormatTokenSource; 58 59 class UnwrappedLineParser { 60 public: 61 UnwrappedLineParser(const FormatStyle &Style, ArrayRef<FormatToken *> Tokens, 62 UnwrappedLineConsumer &Callback); 63 64 /// Returns true in case of a structural error. 65 bool parse(); 66 67 private: 68 void parseFile(); 69 void parseLevel(bool HasOpeningBrace); 70 void parseBlock(bool MustBeDeclaration, unsigned AddLevels = 1); 71 void parsePPDirective(); 72 void parsePPDefine(); 73 void parsePPIf(); 74 void parsePPIfdef(); 75 void parsePPElIf(); 76 void parsePPElse(); 77 void parsePPEndIf(); 78 void parsePPUnknown(); 79 void parseStructuralElement(); 80 bool tryToParseBracedList(); 81 void parseBracedList(); 82 void parseReturn(); 83 void parseParens(); 84 void parseIfThenElse(); 85 void parseForOrWhileLoop(); 86 void parseDoWhile(); 87 void parseLabel(); 88 void parseCaseLabel(); 89 void parseSwitch(); 90 void parseNamespace(); 91 void parseAccessSpecifier(); 92 void parseEnum(); 93 void parseRecord(); 94 void parseObjCProtocolList(); 95 void parseObjCUntilAtEnd(); 96 void parseObjCInterfaceOrImplementation(); 97 void parseObjCProtocol(); 98 void addUnwrappedLine(); 99 bool eof() const; 100 void nextToken(); 101 void readToken(); 102 void flushComments(bool NewlineBeforeNext); 103 void pushToken(FormatToken *Tok); 104 void calculateBraceTypes(); 105 void pushPPConditional(); 106 107 // Represents what type of block a left brace opens. 108 enum LBraceState { 109 BS_Unknown, 110 BS_Block, 111 BS_BracedInit 112 }; 113 114 // FIXME: We are constantly running into bugs where Line.Level is incorrectly 115 // subtracted from beyond 0. Introduce a method to subtract from Line.Level 116 // and use that everywhere in the Parser. 117 OwningPtr<UnwrappedLine> Line; 118 119 // Comments are sorted into unwrapped lines by whether they are in the same 120 // line as the previous token, or not. If not, they belong to the next token. 121 // Since the next token might already be in a new unwrapped line, we need to 122 // store the comments belonging to that token. 123 SmallVector<FormatToken *, 1> CommentsBeforeNextToken; 124 FormatToken *FormatTok; 125 bool MustBreakBeforeNextToken; 126 127 // The parsed lines. Only added to through \c CurrentLines. 128 std::vector<UnwrappedLine> Lines; 129 130 // Preprocessor directives are parsed out-of-order from other unwrapped lines. 131 // Thus, we need to keep a list of preprocessor directives to be reported 132 // after an unwarpped line that has been started was finished. 133 std::vector<UnwrappedLine> PreprocessorDirectives; 134 135 // New unwrapped lines are added via CurrentLines. 136 // Usually points to \c &Lines. While parsing a preprocessor directive when 137 // there is an unfinished previous unwrapped line, will point to 138 // \c &PreprocessorDirectives. 139 std::vector<UnwrappedLine> *CurrentLines; 140 141 // We store for each line whether it must be a declaration depending on 142 // whether we are in a compound statement or not. 143 std::vector<bool> DeclarationScopeStack; 144 145 // Will be true if we encounter an error that leads to possibily incorrect 146 // indentation levels. 147 bool StructuralError; 148 149 const FormatStyle &Style; 150 FormatTokenSource *Tokens; 151 UnwrappedLineConsumer &Callback; 152 153 // FIXME: This is a temporary measure until we have reworked the ownership 154 // of the format tokens. The goal is to have the actual tokens created and 155 // owned outside of and handed into the UnwrappedLineParser. 156 ArrayRef<FormatToken *> AllTokens; 157 158 // FIXME: Currently we cannot store attributes with tokens, as we treat 159 // them as read-only; thus, we now store the brace state indexed by the 160 // position of the token in the stream (see \c AllTokens). 161 SmallVector<LBraceState, 16> LBraces; 162 163 // Represents preprocessor branch type, so we can find matching 164 // #if/#else/#endif directives. 165 enum PPBranchKind { 166 PP_Conditional, // Any #if, #ifdef, #ifndef, #elif, block outside #if 0 167 PP_Unreachable // #if 0 or a conditional preprocessor block inside #if 0 168 }; 169 170 // Keeps a stack of currently active preprocessor branching directives. 171 SmallVector<PPBranchKind, 16> PPStack; 172 173 friend class ScopedLineState; 174 }; 175 176 } // end namespace format 177 } // end namespace clang 178 179 #endif // LLVM_CLANG_FORMAT_UNWRAPPED_LINE_PARSER_H 180