blob: dffc309a09efe13145eb3866723e200cf43f275e [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 Klimek36fab8d2013-01-10 13:24:24 +0000173 if (!FormatTok.Tok.is(tok::r_brace)) {
174 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000175
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000176 Line->Level += AddLevels;
177 parseLevel(/*HasOpeningBrace=*/true);
178 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000179
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000180 if (!FormatTok.Tok.is(tok::r_brace))
181 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000182
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000183 }
Manuel Klimekde768542013-01-07 18:10:23 +0000184 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000185 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000186}
187
188void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000189 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000190 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000191 nextToken();
192
Manuel Klimeka080a182013-01-02 16:30:12 +0000193 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
194 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000195 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000196 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000197
Manuel Klimekd4397b92013-01-04 23:34:14 +0000198 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
199 case tok::pp_define:
200 parsePPDefine();
201 break;
202 default:
203 parsePPUnknown();
204 break;
205 }
206}
207
208void UnwrappedLineParser::parsePPDefine() {
209 nextToken();
210
211 if (FormatTok.Tok.getKind() != tok::identifier) {
212 parsePPUnknown();
213 return;
214 }
215 nextToken();
216 if (FormatTok.Tok.getKind() == tok::l_paren) {
217 parseParens();
218 }
219 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000220 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000221
222 // Errors during a preprocessor directive can only affect the layout of the
223 // preprocessor directive, and thus we ignore them. An alternative approach
224 // would be to use the same approach we use on the file level (no
225 // re-indentation if there was a structural error) within the macro
226 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000227 parseFile();
228}
229
230void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000231 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000232 nextToken();
233 } while (!eof());
234 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000235}
236
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000237void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000238 // Consume leading line comments, e.g. for branches without compounds.
239 while (FormatTok.Tok.is(tok::comment)) {
240 nextToken();
241 addUnwrappedLine();
242 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000243}
244
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000245void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000246 assert(!FormatTok.Tok.is(tok::l_brace));
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000247 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000248
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000249 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000250 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000251 case tok::at:
252 nextToken();
253 switch (FormatTok.Tok.getObjCKeywordID()) {
254 case tok::objc_public:
255 case tok::objc_protected:
256 case tok::objc_package:
257 case tok::objc_private:
258 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000259 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000260 case tok::objc_implementation:
261 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000262 case tok::objc_protocol:
263 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000264 case tok::objc_end:
265 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000266 case tok::objc_optional:
267 case tok::objc_required:
268 nextToken();
269 addUnwrappedLine();
270 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000271 default:
272 break;
273 }
274 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000275 case tok::kw_namespace:
276 parseNamespace();
277 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000278 case tok::kw_inline:
279 nextToken();
280 TokenNumber++;
281 if (FormatTok.Tok.is(tok::kw_namespace)) {
282 parseNamespace();
283 return;
284 }
285 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000286 case tok::kw_public:
287 case tok::kw_protected:
288 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000289 parseAccessSpecifier();
290 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000291 case tok::kw_if:
292 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000293 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000294 case tok::kw_for:
295 case tok::kw_while:
296 parseForOrWhileLoop();
297 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000298 case tok::kw_do:
299 parseDoWhile();
300 return;
301 case tok::kw_switch:
302 parseSwitch();
303 return;
304 case tok::kw_default:
305 nextToken();
306 parseLabel();
307 return;
308 case tok::kw_case:
309 parseCaseLabel();
310 return;
Manuel Klimekc44ee892013-01-21 10:07:49 +0000311 case tok::kw_return:
312 parseReturn();
313 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000314 default:
315 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000316 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000317 do {
318 ++TokenNumber;
319 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000320 case tok::kw_enum:
321 parseEnum();
322 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000323 case tok::kw_struct:
324 case tok::kw_union:
Manuel Klimekde768542013-01-07 18:10:23 +0000325 case tok::kw_class:
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000326 parseRecord();
327 // A record declaration or definition is always the start of a structural
328 // element.
329 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000330 case tok::semi:
331 nextToken();
332 addUnwrappedLine();
333 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000334 case tok::r_brace:
335 addUnwrappedLine();
336 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000337 case tok::l_paren:
338 parseParens();
339 break;
340 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000341 // A block outside of parentheses must be the last part of a
342 // structural element.
343 // FIXME: Figure out cases where this is not true, and add projections for
344 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000345 parseBlock();
346 addUnwrappedLine();
347 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000348 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000349 nextToken();
350 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
351 parseLabel();
352 return;
353 }
354 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000355 case tok::equal:
356 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000357 if (FormatTok.Tok.is(tok::l_brace)) {
358 parseBracedList();
359 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000360 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000361 default:
362 nextToken();
363 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000364 }
365 } while (!eof());
366}
367
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000368void UnwrappedLineParser::parseBracedList() {
369 nextToken();
370
371 do {
372 switch (FormatTok.Tok.getKind()) {
373 case tok::l_brace:
374 parseBracedList();
375 break;
376 case tok::r_brace:
377 nextToken();
378 return;
379 default:
380 nextToken();
381 break;
382 }
383 } while (!eof());
384}
385
Manuel Klimekc44ee892013-01-21 10:07:49 +0000386void UnwrappedLineParser::parseReturn() {
387 nextToken();
388
389 do {
390 switch (FormatTok.Tok.getKind()) {
391 case tok::l_brace:
392 parseBracedList();
393 break;
394 case tok::l_paren:
395 parseParens();
396 break;
397 case tok::r_brace:
398 // Assume missing ';'.
399 addUnwrappedLine();
400 return;
401 case tok::semi:
402 nextToken();
403 addUnwrappedLine();
404 return;
405 default:
406 nextToken();
407 break;
408 }
409 } while (!eof());
410}
411
Daniel Jasperbac016b2012-12-03 18:12:45 +0000412void UnwrappedLineParser::parseParens() {
413 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
414 nextToken();
415 do {
416 switch (FormatTok.Tok.getKind()) {
417 case tok::l_paren:
418 parseParens();
419 break;
420 case tok::r_paren:
421 nextToken();
422 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000423 case tok::l_brace:
424 {
425 nextToken();
426 ScopedLineState LineState(*this);
427 Line->Level += 1;
428 parseLevel(/*HasOpeningBrace=*/true);
429 Line->Level -= 1;
430 }
431 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000432 default:
433 nextToken();
434 break;
435 }
436 } while (!eof());
437}
438
439void UnwrappedLineParser::parseIfThenElse() {
440 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
441 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000442 if (FormatTok.Tok.is(tok::l_paren))
443 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000444 bool NeedsUnwrappedLine = false;
445 if (FormatTok.Tok.is(tok::l_brace)) {
446 parseBlock();
447 NeedsUnwrappedLine = true;
448 } else {
449 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000450 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000451 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000452 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000453 }
454 if (FormatTok.Tok.is(tok::kw_else)) {
455 nextToken();
456 if (FormatTok.Tok.is(tok::l_brace)) {
457 parseBlock();
458 addUnwrappedLine();
459 } else if (FormatTok.Tok.is(tok::kw_if)) {
460 parseIfThenElse();
461 } else {
462 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000463 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000464 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000465 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000466 }
467 } else if (NeedsUnwrappedLine) {
468 addUnwrappedLine();
469 }
470}
471
Alexander Kornienko15757312012-12-06 18:03:27 +0000472void UnwrappedLineParser::parseNamespace() {
473 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
474 nextToken();
475 if (FormatTok.Tok.is(tok::identifier))
476 nextToken();
477 if (FormatTok.Tok.is(tok::l_brace)) {
478 parseBlock(0);
479 addUnwrappedLine();
480 }
481 // FIXME: Add error handling.
482}
483
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000484void UnwrappedLineParser::parseForOrWhileLoop() {
485 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
486 "'for' or 'while' expected");
487 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000488 if (FormatTok.Tok.is(tok::l_paren))
489 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000490 if (FormatTok.Tok.is(tok::l_brace)) {
491 parseBlock();
492 addUnwrappedLine();
493 } else {
494 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000495 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000496 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000497 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000498 }
499}
500
Daniel Jasperbac016b2012-12-03 18:12:45 +0000501void UnwrappedLineParser::parseDoWhile() {
502 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
503 nextToken();
504 if (FormatTok.Tok.is(tok::l_brace)) {
505 parseBlock();
506 } else {
507 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000508 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000509 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000510 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000511 }
512
Alexander Kornienko393b0082012-12-04 15:40:36 +0000513 // FIXME: Add error handling.
514 if (!FormatTok.Tok.is(tok::kw_while)) {
515 addUnwrappedLine();
516 return;
517 }
518
Daniel Jasperbac016b2012-12-03 18:12:45 +0000519 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000520 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000521}
522
523void UnwrappedLineParser::parseLabel() {
524 // FIXME: remove all asserts.
525 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
526 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000527 unsigned OldLineLevel = Line->Level;
528 if (Line->Level > 0)
529 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000530 if (FormatTok.Tok.is(tok::l_brace)) {
531 parseBlock();
Nico Weber94fb7292013-01-18 05:50:57 +0000532 if (FormatTok.Tok.is(tok::kw_break))
533 parseStructuralElement(); // "break;" after "}" goes on the same line.
Daniel Jasperbac016b2012-12-03 18:12:45 +0000534 }
535 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000536 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000537}
538
539void UnwrappedLineParser::parseCaseLabel() {
540 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
541 // FIXME: fix handling of complex expressions here.
542 do {
543 nextToken();
544 } while (!eof() && !FormatTok.Tok.is(tok::colon));
545 parseLabel();
546}
547
548void UnwrappedLineParser::parseSwitch() {
549 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
550 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000551 if (FormatTok.Tok.is(tok::l_paren))
552 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000553 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000554 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000555 addUnwrappedLine();
556 } else {
557 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000558 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000559 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000560 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000561 }
562}
563
564void UnwrappedLineParser::parseAccessSpecifier() {
565 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000566 // Otherwise, we don't know what it is, and we'd better keep the next token.
567 if (FormatTok.Tok.is(tok::colon))
568 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000569 addUnwrappedLine();
570}
571
572void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000573 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000574 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000575 switch (FormatTok.Tok.getKind()) {
576 case tok::l_brace:
577 nextToken();
578 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000579 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000580 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000581 break;
582 case tok::l_paren:
583 parseParens();
584 break;
585 case tok::comma:
586 nextToken();
587 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000588 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000589 break;
590 case tok::r_brace:
591 if (HasContents)
592 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000593 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000594 nextToken();
595 break;
596 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000597 nextToken();
598 addUnwrappedLine();
599 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000600 default:
601 HasContents = true;
602 nextToken();
603 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000604 }
605 } while (!eof());
606}
607
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000608void UnwrappedLineParser::parseRecord() {
Manuel Klimekde768542013-01-07 18:10:23 +0000609 nextToken();
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000610 if (FormatTok.Tok.is(tok::identifier) ||
611 FormatTok.Tok.is(tok::kw___attribute) ||
612 FormatTok.Tok.is(tok::kw___declspec)) {
613 nextToken();
614 // We can have macros or attributes in between 'class' and the class name.
615 if (FormatTok.Tok.is(tok::l_paren)) {
616 parseParens();
Manuel Klimekde768542013-01-07 18:10:23 +0000617 }
Manuel Klimek7f5b0252013-01-21 10:17:14 +0000618 // The actual identifier can be a nested name specifier.
619 while (FormatTok.Tok.is(tok::identifier) ||
620 FormatTok.Tok.is(tok::coloncolon))
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000621 nextToken();
622
623 if (FormatTok.Tok.is(tok::colon)) {
624 while (FormatTok.Tok.isNot(tok::l_brace)) {
625 if (FormatTok.Tok.is(tok::semi))
626 return;
627 nextToken();
628 }
629 }
630 }
631 if (FormatTok.Tok.is(tok::l_brace))
632 parseBlock();
Manuel Klimekde768542013-01-07 18:10:23 +0000633}
634
Nico Weber1abe6ea2013-01-09 21:15:03 +0000635void UnwrappedLineParser::parseObjCProtocolList() {
636 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
637 do
638 nextToken();
639 while (!eof() && FormatTok.Tok.isNot(tok::greater));
640 nextToken(); // Skip '>'.
641}
642
643void UnwrappedLineParser::parseObjCUntilAtEnd() {
644 do {
645 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
646 nextToken();
647 addUnwrappedLine();
648 break;
649 }
650 parseStructuralElement();
651 } while (!eof());
652}
653
Nico Weber50767d82013-01-09 23:25:37 +0000654void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000655 nextToken();
656 nextToken(); // interface name
657
658 // @interface can be followed by either a base class, or a category.
659 if (FormatTok.Tok.is(tok::colon)) {
660 nextToken();
661 nextToken(); // base class name
662 } else if (FormatTok.Tok.is(tok::l_paren))
663 // Skip category, if present.
664 parseParens();
665
Nico Weber1abe6ea2013-01-09 21:15:03 +0000666 if (FormatTok.Tok.is(tok::less))
667 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000668
669 // If instance variables are present, keep the '{' on the first line too.
670 if (FormatTok.Tok.is(tok::l_brace))
671 parseBlock();
672
673 // With instance variables, this puts '}' on its own line. Without instance
674 // variables, this ends the @interface line.
675 addUnwrappedLine();
676
Nico Weber1abe6ea2013-01-09 21:15:03 +0000677 parseObjCUntilAtEnd();
678}
Nico Weber27d13672013-01-09 20:25:35 +0000679
Nico Weber1abe6ea2013-01-09 21:15:03 +0000680void UnwrappedLineParser::parseObjCProtocol() {
681 nextToken();
682 nextToken(); // protocol name
683
684 if (FormatTok.Tok.is(tok::less))
685 parseObjCProtocolList();
686
687 // Check for protocol declaration.
688 if (FormatTok.Tok.is(tok::semi)) {
689 nextToken();
690 return addUnwrappedLine();
691 }
692
693 addUnwrappedLine();
694 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000695}
696
Daniel Jasperbac016b2012-12-03 18:12:45 +0000697void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000698 if (Line->Tokens.empty())
Daniel Jasper26f7e782013-01-08 14:56:18 +0000699 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000700 // Consume trailing comments.
701 while (!eof() && FormatTok.NewlinesBefore == 0 &&
702 FormatTok.Tok.is(tok::comment)) {
703 nextToken();
704 }
Manuel Klimek8fa37992013-01-16 12:31:12 +0000705 DEBUG({
706 llvm::dbgs() << "Line: ";
707 for (std::list<FormatToken>::iterator I = Line->Tokens.begin(),
708 E = Line->Tokens.end();
709 I != E; ++I) {
710 llvm::dbgs() << I->Tok.getName() << " ";
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000711
Manuel Klimek8fa37992013-01-16 12:31:12 +0000712 }
713 llvm::dbgs() << "\n";
714 });
Manuel Klimek525fe162013-01-18 14:04:34 +0000715 CurrentLines->push_back(*Line);
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000716 Line->Tokens.clear();
Manuel Klimek525fe162013-01-18 14:04:34 +0000717 if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
718 for (std::vector<UnwrappedLine>::iterator I = PreprocessorDirectives
719 .begin(), E = PreprocessorDirectives.end();
720 I != E; ++I) {
721 CurrentLines->push_back(*I);
722 }
723 PreprocessorDirectives.clear();
724 }
725
Daniel Jasperbac016b2012-12-03 18:12:45 +0000726}
727
728bool UnwrappedLineParser::eof() const {
729 return FormatTok.Tok.is(tok::eof);
730}
731
732void UnwrappedLineParser::nextToken() {
733 if (eof())
734 return;
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000735 Line->Tokens.push_back(FormatTok);
Manuel Klimek526ed112013-01-09 15:25:02 +0000736 if (MustBreakBeforeNextToken) {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000737 Line->Tokens.back().MustBreakBefore = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000738 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000739 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000740 readToken();
741}
742
743void UnwrappedLineParser::readToken() {
744 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000745 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000746 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
747 FormatTok.IsFirst)) {
Manuel Klimek525fe162013-01-18 14:04:34 +0000748 // If there is an unfinished unwrapped line, we flush the preprocessor
749 // directives only after that unwrapped line was finished later.
750 bool SwitchToPreprocessorLines = !Line->Tokens.empty() &&
751 CurrentLines == &Lines;
752 ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000753 parsePPDirective();
754 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000755}
756
Daniel Jaspercd162382013-01-07 13:26:07 +0000757} // end namespace format
758} // end namespace clang