blob: c09ee311d3b9b5066698334c0369bdc6c9e8af7e [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
Manuel Klimek4c60fc62013-01-10 10:05:08 +000022// Uncomment to get debug output from the UnwrappedLineParser.
23// Use in combination with --gtest_filter=*TestName* to limit the output to a
24// single test.
25// #define UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
26
Daniel Jasperbac016b2012-12-03 18:12:45 +000027namespace clang {
28namespace format {
29
Manuel Klimekd4397b92013-01-04 23:34:14 +000030class ScopedMacroState : public FormatTokenSource {
31public:
32 ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
33 FormatToken &ResetToken)
34 : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
Manuel Klimekc37b4d62013-01-05 22:14:16 +000035 PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource) {
Manuel Klimekd4397b92013-01-04 23:34:14 +000036 TokenSource = this;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000037 Line.Level = 0;
Manuel Klimekd4397b92013-01-04 23:34:14 +000038 Line.InPPDirective = true;
39 }
40
41 ~ScopedMacroState() {
42 TokenSource = PreviousTokenSource;
43 ResetToken = Token;
44 Line.InPPDirective = false;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000045 Line.Level = PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000046 }
47
48 virtual FormatToken getNextToken() {
Manuel Klimekdd5b1012013-01-07 10:03:37 +000049 // The \c UnwrappedLineParser guards against this by never calling
50 // \c getNextToken() after it has encountered the first eof token.
51 assert(!eof());
Manuel Klimekd4397b92013-01-04 23:34:14 +000052 Token = PreviousTokenSource->getNextToken();
53 if (eof())
54 return createEOF();
55 return Token;
56 }
57
58private:
59 bool eof() {
60 return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline;
61 }
62
63 FormatToken createEOF() {
64 FormatToken FormatTok;
65 FormatTok.Tok.startToken();
66 FormatTok.Tok.setKind(tok::eof);
67 return FormatTok;
68 }
69
70 UnwrappedLine &Line;
71 FormatTokenSource *&TokenSource;
72 FormatToken &ResetToken;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000073 unsigned PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000074 FormatTokenSource *PreviousTokenSource;
75
76 FormatToken Token;
77};
78
Alexander Kornienko469a21b2012-12-07 16:15:44 +000079UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
80 FormatTokenSource &Tokens,
Daniel Jasperbac016b2012-12-03 18:12:45 +000081 UnwrappedLineConsumer &Callback)
Manuel Klimek526ed112013-01-09 15:25:02 +000082 : Line(new UnwrappedLine), RootTokenInitialized(false),
83 LastInCurrentLine(NULL), MustBreakBeforeNextToken(false), Style(Style),
84 Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000085}
86
Alexander Kornienkocff563c2012-12-04 17:27:50 +000087bool UnwrappedLineParser::parse() {
Manuel Klimek4c60fc62013-01-10 10:05:08 +000088#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
89 llvm::errs() << "----\n";
90#endif
Manuel Klimekd4397b92013-01-04 23:34:14 +000091 readToken();
92 return parseFile();
93}
94
95bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +000096 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +000097 // Make sure to format the remaining tokens.
98 addUnwrappedLine();
99 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000100}
101
Manuel Klimeka5342db2013-01-06 20:07:31 +0000102bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000103 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000104 do {
105 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000106 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000107 nextToken();
108 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000109 break;
110 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000111 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000112 addUnwrappedLine();
113 break;
114 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000115 if (HasOpeningBrace) {
116 return false;
117 } else {
118 // Stray '}' is an error.
119 Error = true;
120 nextToken();
121 addUnwrappedLine();
122 }
123 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000124 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000125 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000126 break;
127 }
128 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000129 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000130}
131
Alexander Kornienko15757312012-12-06 18:03:27 +0000132bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000133 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000134 nextToken();
135
Daniel Jasperbac016b2012-12-03 18:12:45 +0000136 addUnwrappedLine();
137
Manuel Klimek526ed112013-01-09 15:25:02 +0000138 Line->Level += AddLevels;
Manuel Klimeka5342db2013-01-06 20:07:31 +0000139 parseLevel(/*HasOpeningBrace=*/true);
Manuel Klimek526ed112013-01-09 15:25:02 +0000140 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000141
Alexander Kornienko393b0082012-12-04 15:40:36 +0000142 if (!FormatTok.Tok.is(tok::r_brace))
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000143 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000144
Manuel Klimekde768542013-01-07 18:10:23 +0000145 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000146 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000147}
148
149void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000150 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000151 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000152 nextToken();
153
Manuel Klimeka080a182013-01-02 16:30:12 +0000154 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
155 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000156 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000157 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000158
Manuel Klimekd4397b92013-01-04 23:34:14 +0000159 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
160 case tok::pp_define:
161 parsePPDefine();
162 break;
163 default:
164 parsePPUnknown();
165 break;
166 }
167}
168
169void UnwrappedLineParser::parsePPDefine() {
170 nextToken();
171
172 if (FormatTok.Tok.getKind() != tok::identifier) {
173 parsePPUnknown();
174 return;
175 }
176 nextToken();
177 if (FormatTok.Tok.getKind() == tok::l_paren) {
178 parseParens();
179 }
180 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000181 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000182
183 // Errors during a preprocessor directive can only affect the layout of the
184 // preprocessor directive, and thus we ignore them. An alternative approach
185 // would be to use the same approach we use on the file level (no
186 // re-indentation if there was a structural error) within the macro
187 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000188 parseFile();
189}
190
191void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000192 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000193 nextToken();
194 } while (!eof());
195 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000196}
197
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000198void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000199 // Consume leading line comments, e.g. for branches without compounds.
200 while (FormatTok.Tok.is(tok::comment)) {
201 nextToken();
202 addUnwrappedLine();
203 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000204}
205
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000206void UnwrappedLineParser::parseStructuralElement() {
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000207 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000208
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000209 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000210 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000211 case tok::at:
212 nextToken();
213 switch (FormatTok.Tok.getObjCKeywordID()) {
214 case tok::objc_public:
215 case tok::objc_protected:
216 case tok::objc_package:
217 case tok::objc_private:
218 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000219 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000220 case tok::objc_implementation:
221 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000222 case tok::objc_protocol:
223 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000224 case tok::objc_end:
225 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000226 case tok::objc_optional:
227 case tok::objc_required:
228 nextToken();
229 addUnwrappedLine();
230 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000231 default:
232 break;
233 }
234 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000235 case tok::kw_namespace:
236 parseNamespace();
237 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000238 case tok::kw_inline:
239 nextToken();
240 TokenNumber++;
241 if (FormatTok.Tok.is(tok::kw_namespace)) {
242 parseNamespace();
243 return;
244 }
245 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000246 case tok::kw_public:
247 case tok::kw_protected:
248 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000249 parseAccessSpecifier();
250 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000251 case tok::kw_if:
252 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000253 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000254 case tok::kw_for:
255 case tok::kw_while:
256 parseForOrWhileLoop();
257 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000258 case tok::kw_do:
259 parseDoWhile();
260 return;
261 case tok::kw_switch:
262 parseSwitch();
263 return;
264 case tok::kw_default:
265 nextToken();
266 parseLabel();
267 return;
268 case tok::kw_case:
269 parseCaseLabel();
270 return;
271 default:
272 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000273 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000274 do {
275 ++TokenNumber;
276 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000277 case tok::kw_enum:
278 parseEnum();
279 return;
Manuel Klimekde768542013-01-07 18:10:23 +0000280 case tok::kw_struct: // fallthrough
281 case tok::kw_class:
282 parseStructOrClass();
283 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000284 case tok::semi:
285 nextToken();
286 addUnwrappedLine();
287 return;
288 case tok::l_paren:
289 parseParens();
290 break;
291 case tok::l_brace:
292 parseBlock();
293 addUnwrappedLine();
294 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000295 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000296 nextToken();
297 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
298 parseLabel();
299 return;
300 }
301 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000302 case tok::equal:
303 nextToken();
304 // Skip initializers as they will be formatted by a later step.
305 if (FormatTok.Tok.is(tok::l_brace))
306 nextToken();
307 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000308 default:
309 nextToken();
310 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000311 }
312 } while (!eof());
313}
314
315void UnwrappedLineParser::parseParens() {
316 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
317 nextToken();
318 do {
319 switch (FormatTok.Tok.getKind()) {
320 case tok::l_paren:
321 parseParens();
322 break;
323 case tok::r_paren:
324 nextToken();
325 return;
326 default:
327 nextToken();
328 break;
329 }
330 } while (!eof());
331}
332
333void UnwrappedLineParser::parseIfThenElse() {
334 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
335 nextToken();
336 parseParens();
337 bool NeedsUnwrappedLine = false;
338 if (FormatTok.Tok.is(tok::l_brace)) {
339 parseBlock();
340 NeedsUnwrappedLine = true;
341 } else {
342 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000343 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000344 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000345 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000346 }
347 if (FormatTok.Tok.is(tok::kw_else)) {
348 nextToken();
349 if (FormatTok.Tok.is(tok::l_brace)) {
350 parseBlock();
351 addUnwrappedLine();
352 } else if (FormatTok.Tok.is(tok::kw_if)) {
353 parseIfThenElse();
354 } else {
355 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000356 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000357 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000358 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000359 }
360 } else if (NeedsUnwrappedLine) {
361 addUnwrappedLine();
362 }
363}
364
Alexander Kornienko15757312012-12-06 18:03:27 +0000365void UnwrappedLineParser::parseNamespace() {
366 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
367 nextToken();
368 if (FormatTok.Tok.is(tok::identifier))
369 nextToken();
370 if (FormatTok.Tok.is(tok::l_brace)) {
371 parseBlock(0);
372 addUnwrappedLine();
373 }
374 // FIXME: Add error handling.
375}
376
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000377void UnwrappedLineParser::parseForOrWhileLoop() {
378 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
379 "'for' or 'while' expected");
380 nextToken();
381 parseParens();
382 if (FormatTok.Tok.is(tok::l_brace)) {
383 parseBlock();
384 addUnwrappedLine();
385 } else {
386 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000387 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000388 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000389 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000390 }
391}
392
Daniel Jasperbac016b2012-12-03 18:12:45 +0000393void UnwrappedLineParser::parseDoWhile() {
394 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
395 nextToken();
396 if (FormatTok.Tok.is(tok::l_brace)) {
397 parseBlock();
398 } else {
399 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000400 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000401 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000402 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000403 }
404
Alexander Kornienko393b0082012-12-04 15:40:36 +0000405 // FIXME: Add error handling.
406 if (!FormatTok.Tok.is(tok::kw_while)) {
407 addUnwrappedLine();
408 return;
409 }
410
Daniel Jasperbac016b2012-12-03 18:12:45 +0000411 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000412 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000413}
414
415void UnwrappedLineParser::parseLabel() {
416 // FIXME: remove all asserts.
417 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
418 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000419 unsigned OldLineLevel = Line->Level;
420 if (Line->Level > 0)
421 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000422 if (FormatTok.Tok.is(tok::l_brace)) {
423 parseBlock();
424 }
425 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000426 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000427}
428
429void UnwrappedLineParser::parseCaseLabel() {
430 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
431 // FIXME: fix handling of complex expressions here.
432 do {
433 nextToken();
434 } while (!eof() && !FormatTok.Tok.is(tok::colon));
435 parseLabel();
436}
437
438void UnwrappedLineParser::parseSwitch() {
439 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
440 nextToken();
441 parseParens();
442 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000443 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000444 addUnwrappedLine();
445 } else {
446 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000447 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000448 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000449 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000450 }
451}
452
453void UnwrappedLineParser::parseAccessSpecifier() {
454 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000455 // Otherwise, we don't know what it is, and we'd better keep the next token.
456 if (FormatTok.Tok.is(tok::colon))
457 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000458 addUnwrappedLine();
459}
460
461void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000462 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000463 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000464 switch (FormatTok.Tok.getKind()) {
465 case tok::l_brace:
466 nextToken();
467 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000468 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000469 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000470 break;
471 case tok::l_paren:
472 parseParens();
473 break;
474 case tok::comma:
475 nextToken();
476 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000477 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000478 break;
479 case tok::r_brace:
480 if (HasContents)
481 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000482 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000483 nextToken();
484 break;
485 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000486 nextToken();
487 addUnwrappedLine();
488 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000489 default:
490 HasContents = true;
491 nextToken();
492 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000493 }
494 } while (!eof());
495}
496
Manuel Klimekde768542013-01-07 18:10:23 +0000497void UnwrappedLineParser::parseStructOrClass() {
498 nextToken();
499 do {
500 switch (FormatTok.Tok.getKind()) {
501 case tok::l_brace:
502 // FIXME: Think about how to resolve the error handling here.
503 parseBlock();
504 parseStructuralElement();
505 return;
506 case tok::semi:
507 nextToken();
508 addUnwrappedLine();
509 return;
510 default:
511 nextToken();
512 break;
513 }
514 } while (!eof());
515}
516
Nico Weber1abe6ea2013-01-09 21:15:03 +0000517void UnwrappedLineParser::parseObjCProtocolList() {
518 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
519 do
520 nextToken();
521 while (!eof() && FormatTok.Tok.isNot(tok::greater));
522 nextToken(); // Skip '>'.
523}
524
525void UnwrappedLineParser::parseObjCUntilAtEnd() {
526 do {
527 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
528 nextToken();
529 addUnwrappedLine();
530 break;
531 }
532 parseStructuralElement();
533 } while (!eof());
534}
535
Nico Weber50767d82013-01-09 23:25:37 +0000536void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000537 nextToken();
538 nextToken(); // interface name
539
540 // @interface can be followed by either a base class, or a category.
541 if (FormatTok.Tok.is(tok::colon)) {
542 nextToken();
543 nextToken(); // base class name
544 } else if (FormatTok.Tok.is(tok::l_paren))
545 // Skip category, if present.
546 parseParens();
547
Nico Weber1abe6ea2013-01-09 21:15:03 +0000548 if (FormatTok.Tok.is(tok::less))
549 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000550
551 // If instance variables are present, keep the '{' on the first line too.
552 if (FormatTok.Tok.is(tok::l_brace))
553 parseBlock();
554
555 // With instance variables, this puts '}' on its own line. Without instance
556 // variables, this ends the @interface line.
557 addUnwrappedLine();
558
Nico Weber1abe6ea2013-01-09 21:15:03 +0000559 parseObjCUntilAtEnd();
560}
Nico Weber27d13672013-01-09 20:25:35 +0000561
Nico Weber1abe6ea2013-01-09 21:15:03 +0000562void UnwrappedLineParser::parseObjCProtocol() {
563 nextToken();
564 nextToken(); // protocol name
565
566 if (FormatTok.Tok.is(tok::less))
567 parseObjCProtocolList();
568
569 // Check for protocol declaration.
570 if (FormatTok.Tok.is(tok::semi)) {
571 nextToken();
572 return addUnwrappedLine();
573 }
574
575 addUnwrappedLine();
576 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000577}
578
Daniel Jasperbac016b2012-12-03 18:12:45 +0000579void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000580 if (!RootTokenInitialized)
581 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000582 // Consume trailing comments.
583 while (!eof() && FormatTok.NewlinesBefore == 0 &&
584 FormatTok.Tok.is(tok::comment)) {
585 nextToken();
586 }
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000587#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
588 FormatToken* NextToken = &Line->RootToken;
589 llvm::errs() << "Line: ";
590 while (NextToken) {
591 llvm::errs() << NextToken->Tok.getName() << " ";
592 NextToken = NextToken->Children.empty() ? NULL : &NextToken->Children[0];
593 }
594 llvm::errs() << "\n";
595#endif
Manuel Klimek526ed112013-01-09 15:25:02 +0000596 Callback.consumeUnwrappedLine(*Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000597 RootTokenInitialized = false;
Manuel Klimek526ed112013-01-09 15:25:02 +0000598 LastInCurrentLine = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000599}
600
601bool UnwrappedLineParser::eof() const {
602 return FormatTok.Tok.is(tok::eof);
603}
604
605void UnwrappedLineParser::nextToken() {
606 if (eof())
607 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000608 if (RootTokenInitialized) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000609 assert(LastInCurrentLine->Children.empty());
Daniel Jasper26f7e782013-01-08 14:56:18 +0000610 LastInCurrentLine->Children.push_back(FormatTok);
611 LastInCurrentLine = &LastInCurrentLine->Children.back();
612 } else {
Manuel Klimek526ed112013-01-09 15:25:02 +0000613 Line->RootToken = FormatTok;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000614 RootTokenInitialized = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000615 LastInCurrentLine = &Line->RootToken;
616 }
617 if (MustBreakBeforeNextToken) {
618 LastInCurrentLine->MustBreakBefore = true;
619 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000620 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000621 readToken();
622}
623
624void UnwrappedLineParser::readToken() {
625 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000626 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000627 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
628 FormatTok.IsFirst)) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000629 UnwrappedLine* StoredLine = Line.take();
630 Line.reset(new UnwrappedLine(*StoredLine));
631 assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty());
632 FormatToken *StoredLastInCurrentLine = LastInCurrentLine;
633 bool PreviousInitialized = RootTokenInitialized;
634 RootTokenInitialized = false;
635 LastInCurrentLine = NULL;
636
Manuel Klimekd4397b92013-01-04 23:34:14 +0000637 parsePPDirective();
Manuel Klimek526ed112013-01-09 15:25:02 +0000638
639 assert(!RootTokenInitialized);
640 Line.reset(StoredLine);
641 RootTokenInitialized = PreviousInitialized;
642 LastInCurrentLine = StoredLastInCurrentLine;
643 assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty());
644 MustBreakBeforeNextToken = true;
Manuel Klimekd4397b92013-01-04 23:34:14 +0000645 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000646}
647
Daniel Jaspercd162382013-01-07 13:26:07 +0000648} // end namespace format
649} // end namespace clang