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_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
17 #define LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H
18 
19 #include "FormatToken.h"
20 #include "clang/Basic/IdentifierTable.h"
21 #include "clang/Format/Format.h"
22 #include "llvm/Support/Regex.h"
23 #include <list>
24 #include <stack>
25 
26 namespace clang {
27 namespace format {
28 
29 struct UnwrappedLineNode;
30 
31 /// \brief An unwrapped line is a sequence of \c Token, that we would like to
32 /// put on a single line if there was no column limit.
33 ///
34 /// This is used as a main interface between the \c UnwrappedLineParser and the
35 /// \c UnwrappedLineFormatter. The key property is that changing the formatting
36 /// within an unwrapped line does not affect any other unwrapped lines.
37 struct UnwrappedLine {
38   UnwrappedLine();
39 
40   // FIXME: Don't use std::list here.
41   /// \brief The \c Tokens comprising this \c UnwrappedLine.
42   std::list<UnwrappedLineNode> Tokens;
43 
44   /// \brief The indent level of the \c UnwrappedLine.
45   unsigned Level;
46 
47   /// \brief Whether this \c UnwrappedLine is part of a preprocessor directive.
48   bool InPPDirective;
49 
50   bool MustBeDeclaration;
51 };
52 
53 class UnwrappedLineConsumer {
54 public:
55   virtual ~UnwrappedLineConsumer() {}
56   virtual void consumeUnwrappedLine(const UnwrappedLine &Line) = 0;
57   virtual void finishRun() = 0;
58 };
59 
60 class FormatTokenSource;
61 
62 class UnwrappedLineParser {
63 public:
64   UnwrappedLineParser(const FormatStyle &Style,
65                       const AdditionalKeywords &Keywords,
66                       ArrayRef<FormatToken *> Tokens,
67                       UnwrappedLineConsumer &Callback);
68 
69   void parse();
70 
71 private:
72   void reset();
73   void parseFile();
74   void parseLevel(bool HasOpeningBrace);
75   void parseBlock(bool MustBeDeclaration, bool AddLevel = true,
76                   bool MunchSemi = true);
77   void parseChildBlock();
78   void parsePPDirective();
79   void parsePPDefine();
80   void parsePPIf(bool IfDef);
81   void parsePPElIf();
82   void parsePPElse();
83   void parsePPEndIf();
84   void parsePPUnknown();
85   void readTokenWithJavaScriptASI();
86   void parseStructuralElement();
87   bool tryToParseBracedList();
88   bool parseBracedList(bool ContinueOnSemicolons = false);
89   void parseParens();
90   void parseSquare();
91   void parseIfThenElse();
92   void parseTryCatch();
93   void parseForOrWhileLoop();
94   void parseDoWhile();
95   void parseLabel();
96   void parseCaseLabel();
97   void parseSwitch();
98   void parseNamespace();
99   void parseNew();
100   void parseAccessSpecifier();
101   bool parseEnum();
102   void parseJavaEnumBody();
103   // Parses a record (aka class) as a top level element. If ParseAsExpr is true,
104   // parses the record as a child block, i.e. if the class declaration is an
105   // expression.
106   void parseRecord(bool ParseAsExpr = false);
107   void parseObjCProtocolList();
108   void parseObjCUntilAtEnd();
109   void parseObjCInterfaceOrImplementation();
110   void parseObjCProtocol();
111   void parseJavaScriptEs6ImportExport();
112   bool tryToParseLambda();
113   bool tryToParseLambdaIntroducer();
114   void tryToParseJSFunction();
115   void addUnwrappedLine();
116   bool eof() const;
117   void nextToken();
118   const FormatToken *getPreviousToken();
119   void readToken();
120 
121   // Decides which comment tokens should be added to the current line and which
122   // should be added as comments before the next token.
123   //
124   // Comments specifies the sequence of comment tokens to analyze. They get
125   // either pushed to the current line or added to the comments before the next
126   // token.
127   //
128   // NextTok specifies the next token. A null pointer NextTok is supported, and
129   // signifies either the absense of a next token, or that the next token
130   // shouldn't be taken into accunt for the analysis.
131   void distributeComments(const SmallVectorImpl<FormatToken *> &Comments,
132                           const FormatToken *NextTok);
133 
134   // Adds the comment preceding the next token to unwrapped lines.
135   void flushComments(bool NewlineBeforeNext);
136   void pushToken(FormatToken *Tok);
137   void calculateBraceTypes(bool ExpectClassBody = false);
138 
139   // Marks a conditional compilation edge (for example, an '#if', '#ifdef',
140   // '#else' or merge conflict marker). If 'Unreachable' is true, assumes
141   // this branch either cannot be taken (for example '#if false'), or should
142   // not be taken in this round.
143   void conditionalCompilationCondition(bool Unreachable);
144   void conditionalCompilationStart(bool Unreachable);
145   void conditionalCompilationAlternative();
146   void conditionalCompilationEnd();
147 
148   bool isOnNewLine(const FormatToken &FormatTok);
149 
150   // FIXME: We are constantly running into bugs where Line.Level is incorrectly
151   // subtracted from beyond 0. Introduce a method to subtract from Line.Level
152   // and use that everywhere in the Parser.
153   std::unique_ptr<UnwrappedLine> Line;
154 
155   // Comments are sorted into unwrapped lines by whether they are in the same
156   // line as the previous token, or not. If not, they belong to the next token.
157   // Since the next token might already be in a new unwrapped line, we need to
158   // store the comments belonging to that token.
159   SmallVector<FormatToken *, 1> CommentsBeforeNextToken;
160   FormatToken *FormatTok;
161   bool MustBreakBeforeNextToken;
162 
163   // The parsed lines. Only added to through \c CurrentLines.
164   SmallVector<UnwrappedLine, 8> Lines;
165 
166   // Preprocessor directives are parsed out-of-order from other unwrapped lines.
167   // Thus, we need to keep a list of preprocessor directives to be reported
168   // after an unwarpped line that has been started was finished.
169   SmallVector<UnwrappedLine, 4> PreprocessorDirectives;
170 
171   // New unwrapped lines are added via CurrentLines.
172   // Usually points to \c &Lines. While parsing a preprocessor directive when
173   // there is an unfinished previous unwrapped line, will point to
174   // \c &PreprocessorDirectives.
175   SmallVectorImpl<UnwrappedLine> *CurrentLines;
176 
177   // We store for each line whether it must be a declaration depending on
178   // whether we are in a compound statement or not.
179   std::vector<bool> DeclarationScopeStack;
180 
181   const FormatStyle &Style;
182   const AdditionalKeywords &Keywords;
183 
184   llvm::Regex CommentPragmasRegex;
185 
186   FormatTokenSource *Tokens;
187   UnwrappedLineConsumer &Callback;
188 
189   // FIXME: This is a temporary measure until we have reworked the ownership
190   // of the format tokens. The goal is to have the actual tokens created and
191   // owned outside of and handed into the UnwrappedLineParser.
192   ArrayRef<FormatToken *> AllTokens;
193 
194   // Represents preprocessor branch type, so we can find matching
195   // #if/#else/#endif directives.
196   enum PPBranchKind {
197     PP_Conditional, // Any #if, #ifdef, #ifndef, #elif, block outside #if 0
198     PP_Unreachable  // #if 0 or a conditional preprocessor block inside #if 0
199   };
200 
201   // Keeps a stack of currently active preprocessor branching directives.
202   SmallVector<PPBranchKind, 16> PPStack;
203 
204   // The \c UnwrappedLineParser re-parses the code for each combination
205   // of preprocessor branches that can be taken.
206   // To that end, we take the same branch (#if, #else, or one of the #elif
207   // branches) for each nesting level of preprocessor branches.
208   // \c PPBranchLevel stores the current nesting level of preprocessor
209   // branches during one pass over the code.
210   int PPBranchLevel;
211 
212   // Contains the current branch (#if, #else or one of the #elif branches)
213   // for each nesting level.
214   SmallVector<int, 8> PPLevelBranchIndex;
215 
216   // Contains the maximum number of branches at each nesting level.
217   SmallVector<int, 8> PPLevelBranchCount;
218 
219   // Contains the number of branches per nesting level we are currently
220   // in while parsing a preprocessor branch sequence.
221   // This is used to update PPLevelBranchCount at the end of a branch
222   // sequence.
223   std::stack<int> PPChainBranchIndex;
224 
225   friend class ScopedLineState;
226   friend class CompoundStatementIndenter;
227 };
228 
229 struct UnwrappedLineNode {
230   UnwrappedLineNode() : Tok(nullptr) {}
231   UnwrappedLineNode(FormatToken *Tok) : Tok(Tok) {}
232 
233   FormatToken *Tok;
234   SmallVector<UnwrappedLine, 0> Children;
235 };
236 
237 inline UnwrappedLine::UnwrappedLine()
238     : Level(0), InPPDirective(false), MustBeDeclaration(false) {}
239 
240 } // end namespace format
241 } // end namespace clang
242 
243 #endif
244