blob: 9b2a1e90e1f70b2b89b96d4ce2db9783bdbe5ce0 [file] [log] [blame]
Daniel Jasperbac016b2012-12-03 18:12:45 +00001//===--- UnwrappedLineParser.cpp - Format C++ code ------------------------===//
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 implementation of the UnwrappedLineParser,
12/// which turns a stream of tokens into UnwrappedLines.
13///
14/// This is EXPERIMENTAL code under heavy development. It is not in a state yet,
15/// where it can be used to format real code.
16///
17//===----------------------------------------------------------------------===//
18
19#include "UnwrappedLineParser.h"
Daniel Jasperbac016b2012-12-03 18:12:45 +000020#include "llvm/Support/raw_ostream.h"
21
22namespace clang {
23namespace format {
24
Manuel Klimekd4397b92013-01-04 23:34:14 +000025class ScopedMacroState : public FormatTokenSource {
26public:
27 ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
28 FormatToken &ResetToken)
29 : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
Manuel Klimekc37b4d62013-01-05 22:14:16 +000030 PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource) {
Manuel Klimekd4397b92013-01-04 23:34:14 +000031 TokenSource = this;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000032 Line.Level = 0;
Manuel Klimekd4397b92013-01-04 23:34:14 +000033 Line.InPPDirective = true;
34 }
35
36 ~ScopedMacroState() {
37 TokenSource = PreviousTokenSource;
38 ResetToken = Token;
39 Line.InPPDirective = false;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000040 Line.Level = PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000041 }
42
43 virtual FormatToken getNextToken() {
Manuel Klimekdd5b1012013-01-07 10:03:37 +000044 // The \c UnwrappedLineParser guards against this by never calling
45 // \c getNextToken() after it has encountered the first eof token.
46 assert(!eof());
Manuel Klimekd4397b92013-01-04 23:34:14 +000047 Token = PreviousTokenSource->getNextToken();
48 if (eof())
49 return createEOF();
50 return Token;
51 }
52
53private:
54 bool eof() {
55 return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline;
56 }
57
58 FormatToken createEOF() {
59 FormatToken FormatTok;
60 FormatTok.Tok.startToken();
61 FormatTok.Tok.setKind(tok::eof);
62 return FormatTok;
63 }
64
65 UnwrappedLine &Line;
66 FormatTokenSource *&TokenSource;
67 FormatToken &ResetToken;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000068 unsigned PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000069 FormatTokenSource *PreviousTokenSource;
70
71 FormatToken Token;
72};
73
Alexander Kornienko469a21b2012-12-07 16:15:44 +000074UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
75 FormatTokenSource &Tokens,
Daniel Jasperbac016b2012-12-03 18:12:45 +000076 UnwrappedLineConsumer &Callback)
Manuel Klimek526ed112013-01-09 15:25:02 +000077 : Line(new UnwrappedLine), RootTokenInitialized(false),
78 LastInCurrentLine(NULL), MustBreakBeforeNextToken(false), Style(Style),
79 Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000080}
81
Alexander Kornienkocff563c2012-12-04 17:27:50 +000082bool UnwrappedLineParser::parse() {
Manuel Klimekd4397b92013-01-04 23:34:14 +000083 readToken();
84 return parseFile();
85}
86
87bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +000088 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +000089 // Make sure to format the remaining tokens.
90 addUnwrappedLine();
91 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +000092}
93
Manuel Klimeka5342db2013-01-06 20:07:31 +000094bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +000095 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +000096 do {
97 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000098 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +000099 nextToken();
100 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000101 break;
102 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000103 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000104 addUnwrappedLine();
105 break;
106 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000107 if (HasOpeningBrace) {
108 return false;
109 } else {
110 // Stray '}' is an error.
111 Error = true;
112 nextToken();
113 addUnwrappedLine();
114 }
115 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000116 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000117 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000118 break;
119 }
120 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000121 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000122}
123
Alexander Kornienko15757312012-12-06 18:03:27 +0000124bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000125 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000126 nextToken();
127
Daniel Jasperbac016b2012-12-03 18:12:45 +0000128 addUnwrappedLine();
129
Manuel Klimek526ed112013-01-09 15:25:02 +0000130 Line->Level += AddLevels;
Manuel Klimeka5342db2013-01-06 20:07:31 +0000131 parseLevel(/*HasOpeningBrace=*/true);
Manuel Klimek526ed112013-01-09 15:25:02 +0000132 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000133
Alexander Kornienko393b0082012-12-04 15:40:36 +0000134 if (!FormatTok.Tok.is(tok::r_brace))
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000135 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000136
Manuel Klimekde768542013-01-07 18:10:23 +0000137 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000138 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000139}
140
141void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000142 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000143 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000144 nextToken();
145
Manuel Klimeka080a182013-01-02 16:30:12 +0000146 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
147 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000148 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000149 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000150
Manuel Klimekd4397b92013-01-04 23:34:14 +0000151 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
152 case tok::pp_define:
153 parsePPDefine();
154 break;
155 default:
156 parsePPUnknown();
157 break;
158 }
159}
160
161void UnwrappedLineParser::parsePPDefine() {
162 nextToken();
163
164 if (FormatTok.Tok.getKind() != tok::identifier) {
165 parsePPUnknown();
166 return;
167 }
168 nextToken();
169 if (FormatTok.Tok.getKind() == tok::l_paren) {
170 parseParens();
171 }
172 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000173 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000174
175 // Errors during a preprocessor directive can only affect the layout of the
176 // preprocessor directive, and thus we ignore them. An alternative approach
177 // would be to use the same approach we use on the file level (no
178 // re-indentation if there was a structural error) within the macro
179 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000180 parseFile();
181}
182
183void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000184 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000185 nextToken();
186 } while (!eof());
187 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000188}
189
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000190void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000191 // Consume leading line comments, e.g. for branches without compounds.
192 while (FormatTok.Tok.is(tok::comment)) {
193 nextToken();
194 addUnwrappedLine();
195 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000196}
197
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000198void UnwrappedLineParser::parseStructuralElement() {
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000199 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000200
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000201 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000202 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000203 case tok::at:
204 nextToken();
205 switch (FormatTok.Tok.getObjCKeywordID()) {
206 case tok::objc_public:
207 case tok::objc_protected:
208 case tok::objc_package:
209 case tok::objc_private:
210 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000211 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000212 case tok::objc_implementation:
213 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000214 case tok::objc_protocol:
215 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000216 case tok::objc_end:
217 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000218 case tok::objc_optional:
219 case tok::objc_required:
220 nextToken();
221 addUnwrappedLine();
222 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000223 default:
224 break;
225 }
226 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000227 case tok::kw_namespace:
228 parseNamespace();
229 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000230 case tok::kw_inline:
231 nextToken();
232 TokenNumber++;
233 if (FormatTok.Tok.is(tok::kw_namespace)) {
234 parseNamespace();
235 return;
236 }
237 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000238 case tok::kw_public:
239 case tok::kw_protected:
240 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000241 parseAccessSpecifier();
242 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000243 case tok::kw_if:
244 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000245 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000246 case tok::kw_for:
247 case tok::kw_while:
248 parseForOrWhileLoop();
249 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000250 case tok::kw_do:
251 parseDoWhile();
252 return;
253 case tok::kw_switch:
254 parseSwitch();
255 return;
256 case tok::kw_default:
257 nextToken();
258 parseLabel();
259 return;
260 case tok::kw_case:
261 parseCaseLabel();
262 return;
263 default:
264 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000265 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000266 do {
267 ++TokenNumber;
268 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000269 case tok::kw_enum:
270 parseEnum();
271 return;
Manuel Klimekde768542013-01-07 18:10:23 +0000272 case tok::kw_struct: // fallthrough
273 case tok::kw_class:
274 parseStructOrClass();
275 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000276 case tok::semi:
277 nextToken();
278 addUnwrappedLine();
279 return;
280 case tok::l_paren:
281 parseParens();
282 break;
283 case tok::l_brace:
284 parseBlock();
285 addUnwrappedLine();
286 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000287 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000288 nextToken();
289 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
290 parseLabel();
291 return;
292 }
293 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000294 case tok::equal:
295 nextToken();
296 // Skip initializers as they will be formatted by a later step.
297 if (FormatTok.Tok.is(tok::l_brace))
298 nextToken();
299 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000300 default:
301 nextToken();
302 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000303 }
304 } while (!eof());
305}
306
307void UnwrappedLineParser::parseParens() {
308 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
309 nextToken();
310 do {
311 switch (FormatTok.Tok.getKind()) {
312 case tok::l_paren:
313 parseParens();
314 break;
315 case tok::r_paren:
316 nextToken();
317 return;
318 default:
319 nextToken();
320 break;
321 }
322 } while (!eof());
323}
324
325void UnwrappedLineParser::parseIfThenElse() {
326 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
327 nextToken();
328 parseParens();
329 bool NeedsUnwrappedLine = false;
330 if (FormatTok.Tok.is(tok::l_brace)) {
331 parseBlock();
332 NeedsUnwrappedLine = true;
333 } else {
334 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000335 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000336 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000337 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000338 }
339 if (FormatTok.Tok.is(tok::kw_else)) {
340 nextToken();
341 if (FormatTok.Tok.is(tok::l_brace)) {
342 parseBlock();
343 addUnwrappedLine();
344 } else if (FormatTok.Tok.is(tok::kw_if)) {
345 parseIfThenElse();
346 } else {
347 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000348 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000349 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000350 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000351 }
352 } else if (NeedsUnwrappedLine) {
353 addUnwrappedLine();
354 }
355}
356
Alexander Kornienko15757312012-12-06 18:03:27 +0000357void UnwrappedLineParser::parseNamespace() {
358 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
359 nextToken();
360 if (FormatTok.Tok.is(tok::identifier))
361 nextToken();
362 if (FormatTok.Tok.is(tok::l_brace)) {
363 parseBlock(0);
364 addUnwrappedLine();
365 }
366 // FIXME: Add error handling.
367}
368
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000369void UnwrappedLineParser::parseForOrWhileLoop() {
370 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
371 "'for' or 'while' expected");
372 nextToken();
373 parseParens();
374 if (FormatTok.Tok.is(tok::l_brace)) {
375 parseBlock();
376 addUnwrappedLine();
377 } else {
378 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000379 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000380 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000381 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000382 }
383}
384
Daniel Jasperbac016b2012-12-03 18:12:45 +0000385void UnwrappedLineParser::parseDoWhile() {
386 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
387 nextToken();
388 if (FormatTok.Tok.is(tok::l_brace)) {
389 parseBlock();
390 } else {
391 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000392 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000393 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000394 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000395 }
396
Alexander Kornienko393b0082012-12-04 15:40:36 +0000397 // FIXME: Add error handling.
398 if (!FormatTok.Tok.is(tok::kw_while)) {
399 addUnwrappedLine();
400 return;
401 }
402
Daniel Jasperbac016b2012-12-03 18:12:45 +0000403 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000404 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000405}
406
407void UnwrappedLineParser::parseLabel() {
408 // FIXME: remove all asserts.
409 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
410 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000411 unsigned OldLineLevel = Line->Level;
412 if (Line->Level > 0)
413 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000414 if (FormatTok.Tok.is(tok::l_brace)) {
415 parseBlock();
416 }
417 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000418 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000419}
420
421void UnwrappedLineParser::parseCaseLabel() {
422 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
423 // FIXME: fix handling of complex expressions here.
424 do {
425 nextToken();
426 } while (!eof() && !FormatTok.Tok.is(tok::colon));
427 parseLabel();
428}
429
430void UnwrappedLineParser::parseSwitch() {
431 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
432 nextToken();
433 parseParens();
434 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000435 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000436 addUnwrappedLine();
437 } else {
438 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000439 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000440 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000441 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000442 }
443}
444
445void UnwrappedLineParser::parseAccessSpecifier() {
446 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000447 // Otherwise, we don't know what it is, and we'd better keep the next token.
448 if (FormatTok.Tok.is(tok::colon))
449 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000450 addUnwrappedLine();
451}
452
453void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000454 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000455 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000456 switch (FormatTok.Tok.getKind()) {
457 case tok::l_brace:
458 nextToken();
459 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000460 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000461 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000462 break;
463 case tok::l_paren:
464 parseParens();
465 break;
466 case tok::comma:
467 nextToken();
468 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000469 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000470 break;
471 case tok::r_brace:
472 if (HasContents)
473 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000474 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000475 nextToken();
476 break;
477 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000478 nextToken();
479 addUnwrappedLine();
480 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000481 default:
482 HasContents = true;
483 nextToken();
484 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000485 }
486 } while (!eof());
487}
488
Manuel Klimekde768542013-01-07 18:10:23 +0000489void UnwrappedLineParser::parseStructOrClass() {
490 nextToken();
491 do {
492 switch (FormatTok.Tok.getKind()) {
493 case tok::l_brace:
494 // FIXME: Think about how to resolve the error handling here.
495 parseBlock();
496 parseStructuralElement();
497 return;
498 case tok::semi:
499 nextToken();
500 addUnwrappedLine();
501 return;
502 default:
503 nextToken();
504 break;
505 }
506 } while (!eof());
507}
508
Nico Weber1abe6ea2013-01-09 21:15:03 +0000509void UnwrappedLineParser::parseObjCProtocolList() {
510 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
511 do
512 nextToken();
513 while (!eof() && FormatTok.Tok.isNot(tok::greater));
514 nextToken(); // Skip '>'.
515}
516
517void UnwrappedLineParser::parseObjCUntilAtEnd() {
518 do {
519 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
520 nextToken();
521 addUnwrappedLine();
522 break;
523 }
524 parseStructuralElement();
525 } while (!eof());
526}
527
Nico Weber50767d82013-01-09 23:25:37 +0000528void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000529 nextToken();
530 nextToken(); // interface name
531
532 // @interface can be followed by either a base class, or a category.
533 if (FormatTok.Tok.is(tok::colon)) {
534 nextToken();
535 nextToken(); // base class name
536 } else if (FormatTok.Tok.is(tok::l_paren))
537 // Skip category, if present.
538 parseParens();
539
Nico Weber1abe6ea2013-01-09 21:15:03 +0000540 if (FormatTok.Tok.is(tok::less))
541 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000542
543 // If instance variables are present, keep the '{' on the first line too.
544 if (FormatTok.Tok.is(tok::l_brace))
545 parseBlock();
546
547 // With instance variables, this puts '}' on its own line. Without instance
548 // variables, this ends the @interface line.
549 addUnwrappedLine();
550
Nico Weber1abe6ea2013-01-09 21:15:03 +0000551 parseObjCUntilAtEnd();
552}
Nico Weber27d13672013-01-09 20:25:35 +0000553
Nico Weber1abe6ea2013-01-09 21:15:03 +0000554void UnwrappedLineParser::parseObjCProtocol() {
555 nextToken();
556 nextToken(); // protocol name
557
558 if (FormatTok.Tok.is(tok::less))
559 parseObjCProtocolList();
560
561 // Check for protocol declaration.
562 if (FormatTok.Tok.is(tok::semi)) {
563 nextToken();
564 return addUnwrappedLine();
565 }
566
567 addUnwrappedLine();
568 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000569}
570
Daniel Jasperbac016b2012-12-03 18:12:45 +0000571void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000572 if (!RootTokenInitialized)
573 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000574 // Consume trailing comments.
575 while (!eof() && FormatTok.NewlinesBefore == 0 &&
576 FormatTok.Tok.is(tok::comment)) {
577 nextToken();
578 }
Manuel Klimek526ed112013-01-09 15:25:02 +0000579 Callback.consumeUnwrappedLine(*Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000580 RootTokenInitialized = false;
Manuel Klimek526ed112013-01-09 15:25:02 +0000581 LastInCurrentLine = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000582}
583
584bool UnwrappedLineParser::eof() const {
585 return FormatTok.Tok.is(tok::eof);
586}
587
588void UnwrappedLineParser::nextToken() {
589 if (eof())
590 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000591 if (RootTokenInitialized) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000592 assert(LastInCurrentLine->Children.empty());
Daniel Jasper26f7e782013-01-08 14:56:18 +0000593 LastInCurrentLine->Children.push_back(FormatTok);
594 LastInCurrentLine = &LastInCurrentLine->Children.back();
595 } else {
Manuel Klimek526ed112013-01-09 15:25:02 +0000596 Line->RootToken = FormatTok;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000597 RootTokenInitialized = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000598 LastInCurrentLine = &Line->RootToken;
599 }
600 if (MustBreakBeforeNextToken) {
601 LastInCurrentLine->MustBreakBefore = true;
602 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000603 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000604 readToken();
605}
606
607void UnwrappedLineParser::readToken() {
608 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000609 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000610 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
611 FormatTok.IsFirst)) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000612 UnwrappedLine* StoredLine = Line.take();
613 Line.reset(new UnwrappedLine(*StoredLine));
614 assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty());
615 FormatToken *StoredLastInCurrentLine = LastInCurrentLine;
616 bool PreviousInitialized = RootTokenInitialized;
617 RootTokenInitialized = false;
618 LastInCurrentLine = NULL;
619
Manuel Klimekd4397b92013-01-04 23:34:14 +0000620 parsePPDirective();
Manuel Klimek526ed112013-01-09 15:25:02 +0000621
622 assert(!RootTokenInitialized);
623 Line.reset(StoredLine);
624 RootTokenInitialized = PreviousInitialized;
625 LastInCurrentLine = StoredLastInCurrentLine;
626 assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty());
627 MustBreakBeforeNextToken = true;
Manuel Klimekd4397b92013-01-04 23:34:14 +0000628 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000629}
630
Daniel Jaspercd162382013-01-07 13:26:07 +0000631} // end namespace format
632} // end namespace clang