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 // FIXME: Don't use std::list here. 37 /// \brief The \c Tokens comprising this \c UnwrappedLine. 38 std::list<FormatToken *> Tokens; 39 40 /// \brief The indent level of the \c UnwrappedLine. 41 unsigned Level; 42 43 /// \brief Whether this \c UnwrappedLine is part of a preprocessor directive. 44 bool InPPDirective; 45 46 bool MustBeDeclaration; 47 }; 48 49 class UnwrappedLineConsumer { 50 public: 51 virtual ~UnwrappedLineConsumer() {} 52 virtual void consumeUnwrappedLine(const UnwrappedLine &Line) = 0; 53 }; 54 55 class FormatTokenSource; 56 57 class UnwrappedLineParser { 58 public: 59 UnwrappedLineParser(const FormatStyle &Style, ArrayRef<FormatToken *> Tokens, 60 UnwrappedLineConsumer &Callback); 61 62 /// Returns true in case of a structural error. 63 bool parse(); 64 65 private: 66 void parseFile(); 67 void parseLevel(bool HasOpeningBrace); 68 void parseBlock(bool MustBeDeclaration, bool AddLevel = true); 69 void parsePPDirective(); 70 void parsePPDefine(); 71 void parsePPIf(); 72 void parsePPIfdef(); 73 void parsePPElIf(); 74 void parsePPElse(); 75 void parsePPEndIf(); 76 void parsePPUnknown(); 77 void parseStructuralElement(); 78 bool tryToParseBracedList(); 79 void parseBracedList(); 80 void parseReturn(); 81 void parseParens(); 82 void parseIfThenElse(); 83 void parseForOrWhileLoop(); 84 void parseDoWhile(); 85 void parseLabel(); 86 void parseCaseLabel(); 87 void parseSwitch(); 88 void parseNamespace(); 89 void parseAccessSpecifier(); 90 void parseEnum(); 91 void parseRecord(); 92 void parseObjCProtocolList(); 93 void parseObjCUntilAtEnd(); 94 void parseObjCInterfaceOrImplementation(); 95 void parseObjCProtocol(); 96 void addUnwrappedLine(); 97 bool eof() const; 98 void nextToken(); 99 void readToken(); 100 void flushComments(bool NewlineBeforeNext); 101 void pushToken(FormatToken *Tok); 102 void calculateBraceTypes(); 103 void pushPPConditional(); 104 105 // FIXME: We are constantly running into bugs where Line.Level is incorrectly 106 // subtracted from beyond 0. Introduce a method to subtract from Line.Level 107 // and use that everywhere in the Parser. 108 OwningPtr<UnwrappedLine> Line; 109 110 // Comments are sorted into unwrapped lines by whether they are in the same 111 // line as the previous token, or not. If not, they belong to the next token. 112 // Since the next token might already be in a new unwrapped line, we need to 113 // store the comments belonging to that token. 114 SmallVector<FormatToken *, 1> CommentsBeforeNextToken; 115 FormatToken *FormatTok; 116 bool MustBreakBeforeNextToken; 117 118 // The parsed lines. Only added to through \c CurrentLines. 119 std::vector<UnwrappedLine> Lines; 120 121 // Preprocessor directives are parsed out-of-order from other unwrapped lines. 122 // Thus, we need to keep a list of preprocessor directives to be reported 123 // after an unwarpped line that has been started was finished. 124 std::vector<UnwrappedLine> PreprocessorDirectives; 125 126 // New unwrapped lines are added via CurrentLines. 127 // Usually points to \c &Lines. While parsing a preprocessor directive when 128 // there is an unfinished previous unwrapped line, will point to 129 // \c &PreprocessorDirectives. 130 std::vector<UnwrappedLine> *CurrentLines; 131 132 // We store for each line whether it must be a declaration depending on 133 // whether we are in a compound statement or not. 134 std::vector<bool> DeclarationScopeStack; 135 136 // Will be true if we encounter an error that leads to possibily incorrect 137 // indentation levels. 138 bool StructuralError; 139 140 const FormatStyle &Style; 141 FormatTokenSource *Tokens; 142 UnwrappedLineConsumer &Callback; 143 144 // FIXME: This is a temporary measure until we have reworked the ownership 145 // of the format tokens. The goal is to have the actual tokens created and 146 // owned outside of and handed into the UnwrappedLineParser. 147 ArrayRef<FormatToken *> AllTokens; 148 149 // Represents preprocessor branch type, so we can find matching 150 // #if/#else/#endif directives. 151 enum PPBranchKind { 152 PP_Conditional, // Any #if, #ifdef, #ifndef, #elif, block outside #if 0 153 PP_Unreachable // #if 0 or a conditional preprocessor block inside #if 0 154 }; 155 156 // Keeps a stack of currently active preprocessor branching directives. 157 SmallVector<PPBranchKind, 16> PPStack; 158 159 friend class ScopedLineState; 160 }; 161 162 } // end namespace format 163 } // end namespace clang 164 165 #endif // LLVM_CLANG_FORMAT_UNWRAPPED_LINE_PARSER_H 166