blob: 2d6c5cf07070a50c60a7f065fe65027e3510f962 [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
Manuel Klimek8fa37992013-01-16 12:31:12 +000019#define DEBUG_TYPE "format-parser"
Daniel Jasperbac016b2012-12-03 18:12:45 +000020
Chandler Carruthb1ba0ef2013-01-19 08:09:44 +000021#include "UnwrappedLineParser.h"
Manuel Klimek8fa37992013-01-16 12:31:12 +000022#include "clang/Basic/Diagnostic.h"
23#include "llvm/Support/Debug.h"
Manuel Klimek8fa37992013-01-16 12:31:12 +000024
25// Uncomment to get debug output from tests:
26// #define DEBUG_WITH_TYPE(T, X) do { X; } while(0)
Manuel Klimek4c60fc62013-01-10 10:05:08 +000027
Daniel Jasperbac016b2012-12-03 18:12:45 +000028namespace clang {
29namespace format {
30
Manuel Klimekd4397b92013-01-04 23:34:14 +000031class ScopedMacroState : public FormatTokenSource {
32public:
33 ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
34 FormatToken &ResetToken)
35 : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
Manuel Klimekc37b4d62013-01-05 22:14:16 +000036 PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource) {
Manuel Klimekd4397b92013-01-04 23:34:14 +000037 TokenSource = this;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000038 Line.Level = 0;
Manuel Klimekd4397b92013-01-04 23:34:14 +000039 Line.InPPDirective = true;
40 }
41
42 ~ScopedMacroState() {
43 TokenSource = PreviousTokenSource;
44 ResetToken = Token;
45 Line.InPPDirective = false;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000046 Line.Level = PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000047 }
48
49 virtual FormatToken getNextToken() {
Manuel Klimekdd5b1012013-01-07 10:03:37 +000050 // The \c UnwrappedLineParser guards against this by never calling
51 // \c getNextToken() after it has encountered the first eof token.
52 assert(!eof());
Manuel Klimekd4397b92013-01-04 23:34:14 +000053 Token = PreviousTokenSource->getNextToken();
54 if (eof())
55 return createEOF();
56 return Token;
57 }
58
59private:
60 bool eof() {
61 return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline;
62 }
63
64 FormatToken createEOF() {
65 FormatToken FormatTok;
66 FormatTok.Tok.startToken();
67 FormatTok.Tok.setKind(tok::eof);
68 return FormatTok;
69 }
70
71 UnwrappedLine &Line;
72 FormatTokenSource *&TokenSource;
73 FormatToken &ResetToken;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000074 unsigned PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000075 FormatTokenSource *PreviousTokenSource;
76
77 FormatToken Token;
78};
79
Manuel Klimekbb42bf12013-01-10 11:52:21 +000080class ScopedLineState {
81public:
Manuel Klimek525fe162013-01-18 14:04:34 +000082 ScopedLineState(UnwrappedLineParser &Parser,
83 bool SwitchToPreprocessorLines = false)
84 : Parser(Parser), SwitchToPreprocessorLines(SwitchToPreprocessorLines) {
85 if (SwitchToPreprocessorLines)
86 Parser.CurrentLines = &Parser.PreprocessorDirectives;
Manuel Klimekbb42bf12013-01-10 11:52:21 +000087 PreBlockLine = Parser.Line.take();
Daniel Jaspercbb6c412013-01-16 09:10:19 +000088 Parser.Line.reset(new UnwrappedLine());
89 Parser.Line->Level = PreBlockLine->Level;
90 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
Manuel Klimekbb42bf12013-01-10 11:52:21 +000091 }
92
93 ~ScopedLineState() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +000094 if (!Parser.Line->Tokens.empty()) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +000095 Parser.addUnwrappedLine();
96 }
Daniel Jaspercbb6c412013-01-16 09:10:19 +000097 assert(Parser.Line->Tokens.empty());
Manuel Klimekbb42bf12013-01-10 11:52:21 +000098 Parser.Line.reset(PreBlockLine);
Manuel Klimekbb42bf12013-01-10 11:52:21 +000099 Parser.MustBreakBeforeNextToken = true;
Manuel Klimek525fe162013-01-18 14:04:34 +0000100 if (SwitchToPreprocessorLines)
101 Parser.CurrentLines = &Parser.Lines;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000102 }
103
104private:
105 UnwrappedLineParser &Parser;
Manuel Klimek525fe162013-01-18 14:04:34 +0000106 const bool SwitchToPreprocessorLines;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000107
108 UnwrappedLine *PreBlockLine;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000109};
110
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000111UnwrappedLineParser::UnwrappedLineParser(
112 clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
113 FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback)
Manuel Klimek525fe162013-01-18 14:04:34 +0000114 : Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
115 CurrentLines(&Lines), Diag(Diag), Style(Style), Tokens(&Tokens),
116 Callback(Callback) {}
Daniel Jasperbac016b2012-12-03 18:12:45 +0000117
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000118bool UnwrappedLineParser::parse() {
Manuel Klimek8fa37992013-01-16 12:31:12 +0000119 DEBUG(llvm::dbgs() << "----\n");
Manuel Klimekd4397b92013-01-04 23:34:14 +0000120 readToken();
Manuel Klimek525fe162013-01-18 14:04:34 +0000121 bool Error = parseFile();
122 for (std::vector<UnwrappedLine>::iterator I = Lines.begin(),
123 E = Lines.end();
124 I != E; ++I) {
125 Callback.consumeUnwrappedLine(*I);
126 }
127 return Error;
Manuel Klimekd4397b92013-01-04 23:34:14 +0000128}
129
130bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +0000131 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000132 // Make sure to format the remaining tokens.
133 addUnwrappedLine();
134 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000135}
136
Manuel Klimeka5342db2013-01-06 20:07:31 +0000137bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000138 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000139 do {
140 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000141 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000142 nextToken();
143 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000144 break;
145 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000146 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000147 addUnwrappedLine();
148 break;
149 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000150 if (HasOpeningBrace) {
151 return false;
152 } else {
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000153 Diag.Report(FormatTok.Tok.getLocation(),
154 Diag.getCustomDiagID(clang::DiagnosticsEngine::Error,
Alexander Kornienko276a2092013-01-11 16:03:45 +0000155 "unexpected '}'"));
Manuel Klimeka5342db2013-01-06 20:07:31 +0000156 Error = true;
157 nextToken();
158 addUnwrappedLine();
159 }
160 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000161 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000162 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000163 break;
164 }
165 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000166 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000167}
168
Alexander Kornienko15757312012-12-06 18:03:27 +0000169bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000170 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000171 nextToken();
172
Manuel Klimek2f1ac412013-01-21 16:42:44 +0000173 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000174
Manuel Klimek2f1ac412013-01-21 16:42:44 +0000175 Line->Level += AddLevels;
176 parseLevel(/*HasOpeningBrace=*/true);
177 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000178
Manuel Klimek2f1ac412013-01-21 16:42:44 +0000179 if (!FormatTok.Tok.is(tok::r_brace))
180 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000181
Manuel Klimekde768542013-01-07 18:10:23 +0000182 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000183 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000184}
185
186void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000187 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000188 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000189 nextToken();
190
Manuel Klimeka080a182013-01-02 16:30:12 +0000191 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
192 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000193 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000194 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000195
Manuel Klimekd4397b92013-01-04 23:34:14 +0000196 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
197 case tok::pp_define:
198 parsePPDefine();
199 break;
200 default:
201 parsePPUnknown();
202 break;
203 }
204}
205
206void UnwrappedLineParser::parsePPDefine() {
207 nextToken();
208
209 if (FormatTok.Tok.getKind() != tok::identifier) {
210 parsePPUnknown();
211 return;
212 }
213 nextToken();
214 if (FormatTok.Tok.getKind() == tok::l_paren) {
215 parseParens();
216 }
217 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000218 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000219
220 // Errors during a preprocessor directive can only affect the layout of the
221 // preprocessor directive, and thus we ignore them. An alternative approach
222 // would be to use the same approach we use on the file level (no
223 // re-indentation if there was a structural error) within the macro
224 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000225 parseFile();
226}
227
228void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000229 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000230 nextToken();
231 } while (!eof());
232 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000233}
234
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000235void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000236 // Consume leading line comments, e.g. for branches without compounds.
237 while (FormatTok.Tok.is(tok::comment)) {
238 nextToken();
239 addUnwrappedLine();
240 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000241}
242
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000243void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000244 assert(!FormatTok.Tok.is(tok::l_brace));
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000245 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000246
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000247 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000248 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000249 case tok::at:
250 nextToken();
251 switch (FormatTok.Tok.getObjCKeywordID()) {
252 case tok::objc_public:
253 case tok::objc_protected:
254 case tok::objc_package:
255 case tok::objc_private:
256 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000257 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000258 case tok::objc_implementation:
259 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000260 case tok::objc_protocol:
261 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000262 case tok::objc_end:
263 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000264 case tok::objc_optional:
265 case tok::objc_required:
266 nextToken();
267 addUnwrappedLine();
268 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000269 default:
270 break;
271 }
272 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000273 case tok::kw_namespace:
274 parseNamespace();
275 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000276 case tok::kw_inline:
277 nextToken();
278 TokenNumber++;
279 if (FormatTok.Tok.is(tok::kw_namespace)) {
280 parseNamespace();
281 return;
282 }
283 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000284 case tok::kw_public:
285 case tok::kw_protected:
286 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000287 parseAccessSpecifier();
288 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000289 case tok::kw_if:
290 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000291 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000292 case tok::kw_for:
293 case tok::kw_while:
294 parseForOrWhileLoop();
295 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000296 case tok::kw_do:
297 parseDoWhile();
298 return;
299 case tok::kw_switch:
300 parseSwitch();
301 return;
302 case tok::kw_default:
303 nextToken();
304 parseLabel();
305 return;
306 case tok::kw_case:
307 parseCaseLabel();
308 return;
Manuel Klimekc44ee892013-01-21 10:07:49 +0000309 case tok::kw_return:
310 parseReturn();
311 return;
Manuel Klimekd19dc2d2013-01-21 14:32:05 +0000312 case tok::kw_extern:
313 nextToken();
314 if (FormatTok.Tok.is(tok::string_literal)) {
315 nextToken();
316 if (FormatTok.Tok.is(tok::l_brace)) {
317 parseBlock(0);
318 addUnwrappedLine();
319 return;
320 }
321 }
322 // In all other cases, parse the declaration.
323 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000324 default:
325 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000326 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000327 do {
328 ++TokenNumber;
329 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000330 case tok::kw_enum:
331 parseEnum();
Manuel Klimek308232c2013-01-21 19:17:52 +0000332 break;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000333 case tok::kw_struct:
334 case tok::kw_union:
Manuel Klimekde768542013-01-07 18:10:23 +0000335 case tok::kw_class:
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000336 parseRecord();
337 // A record declaration or definition is always the start of a structural
338 // element.
339 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000340 case tok::semi:
341 nextToken();
342 addUnwrappedLine();
343 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000344 case tok::r_brace:
345 addUnwrappedLine();
346 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000347 case tok::l_paren:
348 parseParens();
349 break;
350 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000351 // A block outside of parentheses must be the last part of a
352 // structural element.
353 // FIXME: Figure out cases where this is not true, and add projections for
354 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000355 parseBlock();
356 addUnwrappedLine();
357 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000358 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000359 nextToken();
360 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
361 parseLabel();
362 return;
363 }
364 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000365 case tok::equal:
366 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000367 if (FormatTok.Tok.is(tok::l_brace)) {
368 parseBracedList();
369 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000370 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000371 default:
372 nextToken();
373 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000374 }
375 } while (!eof());
376}
377
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000378void UnwrappedLineParser::parseBracedList() {
379 nextToken();
380
381 do {
382 switch (FormatTok.Tok.getKind()) {
383 case tok::l_brace:
384 parseBracedList();
385 break;
386 case tok::r_brace:
387 nextToken();
388 return;
389 default:
390 nextToken();
391 break;
392 }
393 } while (!eof());
394}
395
Manuel Klimekc44ee892013-01-21 10:07:49 +0000396void UnwrappedLineParser::parseReturn() {
397 nextToken();
398
399 do {
400 switch (FormatTok.Tok.getKind()) {
401 case tok::l_brace:
402 parseBracedList();
403 break;
404 case tok::l_paren:
405 parseParens();
406 break;
407 case tok::r_brace:
408 // Assume missing ';'.
409 addUnwrappedLine();
410 return;
411 case tok::semi:
412 nextToken();
413 addUnwrappedLine();
414 return;
415 default:
416 nextToken();
417 break;
418 }
419 } while (!eof());
420}
421
Daniel Jasperbac016b2012-12-03 18:12:45 +0000422void UnwrappedLineParser::parseParens() {
423 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
424 nextToken();
425 do {
426 switch (FormatTok.Tok.getKind()) {
427 case tok::l_paren:
428 parseParens();
429 break;
430 case tok::r_paren:
431 nextToken();
432 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000433 case tok::l_brace:
434 {
435 nextToken();
436 ScopedLineState LineState(*this);
437 Line->Level += 1;
438 parseLevel(/*HasOpeningBrace=*/true);
439 Line->Level -= 1;
440 }
441 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000442 default:
443 nextToken();
444 break;
445 }
446 } while (!eof());
447}
448
449void UnwrappedLineParser::parseIfThenElse() {
450 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
451 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000452 if (FormatTok.Tok.is(tok::l_paren))
453 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000454 bool NeedsUnwrappedLine = false;
455 if (FormatTok.Tok.is(tok::l_brace)) {
456 parseBlock();
457 NeedsUnwrappedLine = true;
458 } else {
459 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000460 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000461 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000462 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000463 }
464 if (FormatTok.Tok.is(tok::kw_else)) {
465 nextToken();
466 if (FormatTok.Tok.is(tok::l_brace)) {
467 parseBlock();
468 addUnwrappedLine();
469 } else if (FormatTok.Tok.is(tok::kw_if)) {
470 parseIfThenElse();
471 } else {
472 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000473 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000474 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000475 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000476 }
477 } else if (NeedsUnwrappedLine) {
478 addUnwrappedLine();
479 }
480}
481
Alexander Kornienko15757312012-12-06 18:03:27 +0000482void UnwrappedLineParser::parseNamespace() {
483 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
484 nextToken();
485 if (FormatTok.Tok.is(tok::identifier))
486 nextToken();
487 if (FormatTok.Tok.is(tok::l_brace)) {
488 parseBlock(0);
489 addUnwrappedLine();
490 }
491 // FIXME: Add error handling.
492}
493
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000494void UnwrappedLineParser::parseForOrWhileLoop() {
495 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
496 "'for' or 'while' expected");
497 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000498 if (FormatTok.Tok.is(tok::l_paren))
499 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000500 if (FormatTok.Tok.is(tok::l_brace)) {
501 parseBlock();
502 addUnwrappedLine();
503 } else {
504 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000505 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000506 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000507 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000508 }
509}
510
Daniel Jasperbac016b2012-12-03 18:12:45 +0000511void UnwrappedLineParser::parseDoWhile() {
512 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
513 nextToken();
514 if (FormatTok.Tok.is(tok::l_brace)) {
515 parseBlock();
516 } else {
517 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000518 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000519 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000520 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000521 }
522
Alexander Kornienko393b0082012-12-04 15:40:36 +0000523 // FIXME: Add error handling.
524 if (!FormatTok.Tok.is(tok::kw_while)) {
525 addUnwrappedLine();
526 return;
527 }
528
Daniel Jasperbac016b2012-12-03 18:12:45 +0000529 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000530 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000531}
532
533void UnwrappedLineParser::parseLabel() {
534 // FIXME: remove all asserts.
535 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
536 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000537 unsigned OldLineLevel = Line->Level;
538 if (Line->Level > 0)
539 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000540 if (FormatTok.Tok.is(tok::l_brace)) {
541 parseBlock();
Nico Weber94fb7292013-01-18 05:50:57 +0000542 if (FormatTok.Tok.is(tok::kw_break))
543 parseStructuralElement(); // "break;" after "}" goes on the same line.
Daniel Jasperbac016b2012-12-03 18:12:45 +0000544 }
545 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000546 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000547}
548
549void UnwrappedLineParser::parseCaseLabel() {
550 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
551 // FIXME: fix handling of complex expressions here.
552 do {
553 nextToken();
554 } while (!eof() && !FormatTok.Tok.is(tok::colon));
555 parseLabel();
556}
557
558void UnwrappedLineParser::parseSwitch() {
559 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
560 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000561 if (FormatTok.Tok.is(tok::l_paren))
562 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000563 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000564 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000565 addUnwrappedLine();
566 } else {
567 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000568 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000569 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000570 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000571 }
572}
573
574void UnwrappedLineParser::parseAccessSpecifier() {
575 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000576 // Otherwise, we don't know what it is, and we'd better keep the next token.
577 if (FormatTok.Tok.is(tok::colon))
578 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000579 addUnwrappedLine();
580}
581
582void UnwrappedLineParser::parseEnum() {
Manuel Klimek308232c2013-01-21 19:17:52 +0000583 nextToken();
584 if (FormatTok.Tok.is(tok::identifier) ||
585 FormatTok.Tok.is(tok::kw___attribute) ||
586 FormatTok.Tok.is(tok::kw___declspec)) {
587 nextToken();
588 // We can have macros or attributes in between 'enum' and the enum name.
589 if (FormatTok.Tok.is(tok::l_paren)) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000590 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000591 }
Manuel Klimek308232c2013-01-21 19:17:52 +0000592 if (FormatTok.Tok.is(tok::identifier))
593 nextToken();
594 }
595 if (FormatTok.Tok.is(tok::l_brace)) {
596 nextToken();
597 addUnwrappedLine();
598 ++Line->Level;
599 do {
600 switch (FormatTok.Tok.getKind()) {
601 case tok::comment:
602 // FIXME: Handle comments centrally, instead of special casing
603 // them everywhere.
604 parseComments();
605 break;
606 case tok::l_paren:
607 parseParens();
608 break;
609 case tok::r_brace:
610 addUnwrappedLine();
611 nextToken();
612 --Line->Level;
613 return;
614 case tok::comma:
615 nextToken();
616 addUnwrappedLine();
617 break;
618 default:
619 nextToken();
620 break;
621 }
622 } while (!eof());
623 }
624 // We fall through to parsing a structural element afterwards, so that in
625 // enum A {} n, m;
626 // "} n, m;" will end up in one unwrapped line.
Daniel Jasperbac016b2012-12-03 18:12:45 +0000627}
628
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000629void UnwrappedLineParser::parseRecord() {
Manuel Klimekde768542013-01-07 18:10:23 +0000630 nextToken();
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000631 if (FormatTok.Tok.is(tok::identifier) ||
632 FormatTok.Tok.is(tok::kw___attribute) ||
633 FormatTok.Tok.is(tok::kw___declspec)) {
634 nextToken();
635 // We can have macros or attributes in between 'class' and the class name.
636 if (FormatTok.Tok.is(tok::l_paren)) {
637 parseParens();
Manuel Klimekde768542013-01-07 18:10:23 +0000638 }
Manuel Klimek7f5b0252013-01-21 10:17:14 +0000639 // The actual identifier can be a nested name specifier.
640 while (FormatTok.Tok.is(tok::identifier) ||
641 FormatTok.Tok.is(tok::coloncolon))
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000642 nextToken();
643
Manuel Klimek3a3408c2013-01-21 13:58:54 +0000644 // Note that parsing away template declarations here leads to incorrectly
645 // accepting function declarations as record declarations.
646 // In general, we cannot solve this problem. Consider:
647 // class A<int> B() {}
648 // which can be a function definition or a class definition when B() is a
649 // macro. If we find enough real-world cases where this is a problem, we
650 // can parse for the 'template' keyword in the beginning of the statement,
651 // and thus rule out the record production in case there is no template
652 // (this would still leave us with an ambiguity between template function
653 // and class declarations).
654 if (FormatTok.Tok.is(tok::colon) || FormatTok.Tok.is(tok::less)) {
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000655 while (FormatTok.Tok.isNot(tok::l_brace)) {
656 if (FormatTok.Tok.is(tok::semi))
657 return;
658 nextToken();
659 }
660 }
661 }
662 if (FormatTok.Tok.is(tok::l_brace))
663 parseBlock();
Manuel Klimek3a3408c2013-01-21 13:58:54 +0000664 // We fall through to parsing a structural element afterwards, so
665 // class A {} n, m;
666 // will end up in one unwrapped line.
Manuel Klimekde768542013-01-07 18:10:23 +0000667}
668
Nico Weber1abe6ea2013-01-09 21:15:03 +0000669void UnwrappedLineParser::parseObjCProtocolList() {
670 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
671 do
672 nextToken();
673 while (!eof() && FormatTok.Tok.isNot(tok::greater));
674 nextToken(); // Skip '>'.
675}
676
677void UnwrappedLineParser::parseObjCUntilAtEnd() {
678 do {
679 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
680 nextToken();
681 addUnwrappedLine();
682 break;
683 }
684 parseStructuralElement();
685 } while (!eof());
686}
687
Nico Weber50767d82013-01-09 23:25:37 +0000688void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000689 nextToken();
690 nextToken(); // interface name
691
692 // @interface can be followed by either a base class, or a category.
693 if (FormatTok.Tok.is(tok::colon)) {
694 nextToken();
695 nextToken(); // base class name
696 } else if (FormatTok.Tok.is(tok::l_paren))
697 // Skip category, if present.
698 parseParens();
699
Nico Weber1abe6ea2013-01-09 21:15:03 +0000700 if (FormatTok.Tok.is(tok::less))
701 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000702
703 // If instance variables are present, keep the '{' on the first line too.
704 if (FormatTok.Tok.is(tok::l_brace))
705 parseBlock();
706
707 // With instance variables, this puts '}' on its own line. Without instance
708 // variables, this ends the @interface line.
709 addUnwrappedLine();
710
Nico Weber1abe6ea2013-01-09 21:15:03 +0000711 parseObjCUntilAtEnd();
712}
Nico Weber27d13672013-01-09 20:25:35 +0000713
Nico Weber1abe6ea2013-01-09 21:15:03 +0000714void UnwrappedLineParser::parseObjCProtocol() {
715 nextToken();
716 nextToken(); // protocol name
717
718 if (FormatTok.Tok.is(tok::less))
719 parseObjCProtocolList();
720
721 // Check for protocol declaration.
722 if (FormatTok.Tok.is(tok::semi)) {
723 nextToken();
724 return addUnwrappedLine();
725 }
726
727 addUnwrappedLine();
728 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000729}
730
Daniel Jasperbac016b2012-12-03 18:12:45 +0000731void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000732 if (Line->Tokens.empty())
Daniel Jasper26f7e782013-01-08 14:56:18 +0000733 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000734 // Consume trailing comments.
735 while (!eof() && FormatTok.NewlinesBefore == 0 &&
736 FormatTok.Tok.is(tok::comment)) {
737 nextToken();
738 }
Manuel Klimek8fa37992013-01-16 12:31:12 +0000739 DEBUG({
740 llvm::dbgs() << "Line: ";
741 for (std::list<FormatToken>::iterator I = Line->Tokens.begin(),
742 E = Line->Tokens.end();
743 I != E; ++I) {
744 llvm::dbgs() << I->Tok.getName() << " ";
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000745
Manuel Klimek8fa37992013-01-16 12:31:12 +0000746 }
747 llvm::dbgs() << "\n";
748 });
Manuel Klimek525fe162013-01-18 14:04:34 +0000749 CurrentLines->push_back(*Line);
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000750 Line->Tokens.clear();
Manuel Klimek525fe162013-01-18 14:04:34 +0000751 if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
752 for (std::vector<UnwrappedLine>::iterator I = PreprocessorDirectives
753 .begin(), E = PreprocessorDirectives.end();
754 I != E; ++I) {
755 CurrentLines->push_back(*I);
756 }
757 PreprocessorDirectives.clear();
758 }
759
Daniel Jasperbac016b2012-12-03 18:12:45 +0000760}
761
762bool UnwrappedLineParser::eof() const {
763 return FormatTok.Tok.is(tok::eof);
764}
765
766void UnwrappedLineParser::nextToken() {
767 if (eof())
768 return;
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000769 Line->Tokens.push_back(FormatTok);
Manuel Klimek526ed112013-01-09 15:25:02 +0000770 if (MustBreakBeforeNextToken) {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000771 Line->Tokens.back().MustBreakBefore = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000772 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000773 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000774 readToken();
775}
776
777void UnwrappedLineParser::readToken() {
778 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000779 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000780 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
781 FormatTok.IsFirst)) {
Manuel Klimek525fe162013-01-18 14:04:34 +0000782 // If there is an unfinished unwrapped line, we flush the preprocessor
783 // directives only after that unwrapped line was finished later.
784 bool SwitchToPreprocessorLines = !Line->Tokens.empty() &&
785 CurrentLines == &Lines;
786 ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000787 parsePPDirective();
788 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000789}
790
Daniel Jaspercd162382013-01-07 13:26:07 +0000791} // end namespace format
792} // end namespace clang