blob: 53fa2a32dfb9167b89f6caa9306ac3e98b44ecc1 [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.
Manuel Klimek86721d22013-01-22 16:31:55 +0000133 flushComments(true);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000134 addUnwrappedLine();
135 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000136}
137
Manuel Klimeka5342db2013-01-06 20:07:31 +0000138bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000139 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000140 do {
141 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000142 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000143 nextToken();
144 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000145 break;
146 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000147 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000148 addUnwrappedLine();
149 break;
150 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000151 if (HasOpeningBrace) {
152 return false;
153 } else {
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000154 Diag.Report(FormatTok.Tok.getLocation(),
155 Diag.getCustomDiagID(clang::DiagnosticsEngine::Error,
Alexander Kornienko276a2092013-01-11 16:03:45 +0000156 "unexpected '}'"));
Manuel Klimeka5342db2013-01-06 20:07:31 +0000157 Error = true;
158 nextToken();
159 addUnwrappedLine();
160 }
161 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000162 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000163 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000164 break;
165 }
166 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000167 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000168}
169
Alexander Kornienko15757312012-12-06 18:03:27 +0000170bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000171 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000172 nextToken();
173
Manuel Klimek2f1ac412013-01-21 16:42:44 +0000174 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000175
Manuel Klimek2f1ac412013-01-21 16:42:44 +0000176 Line->Level += AddLevels;
177 parseLevel(/*HasOpeningBrace=*/true);
Alexander Kornienko15757312012-12-06 18:03:27 +0000178
Manuel Klimek86721d22013-01-22 16:31:55 +0000179 if (!FormatTok.Tok.is(tok::r_brace)) {
180 Line->Level -= AddLevels;
Manuel Klimek2f1ac412013-01-21 16:42:44 +0000181 return true;
Manuel Klimek86721d22013-01-22 16:31:55 +0000182 }
Alexander Kornienko393b0082012-12-04 15:40:36 +0000183
Manuel Klimekde768542013-01-07 18:10:23 +0000184 nextToken(); // Munch the closing brace.
Manuel Klimek86721d22013-01-22 16:31:55 +0000185 Line->Level -= AddLevels;
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000186 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000187}
188
189void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000190 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000191 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000192 nextToken();
193
Manuel Klimeka080a182013-01-02 16:30:12 +0000194 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
195 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000196 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000197 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000198
Manuel Klimekd4397b92013-01-04 23:34:14 +0000199 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
200 case tok::pp_define:
201 parsePPDefine();
202 break;
203 default:
204 parsePPUnknown();
205 break;
206 }
207}
208
209void UnwrappedLineParser::parsePPDefine() {
210 nextToken();
211
212 if (FormatTok.Tok.getKind() != tok::identifier) {
213 parsePPUnknown();
214 return;
215 }
216 nextToken();
217 if (FormatTok.Tok.getKind() == tok::l_paren) {
218 parseParens();
219 }
220 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000221 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000222
223 // Errors during a preprocessor directive can only affect the layout of the
224 // preprocessor directive, and thus we ignore them. An alternative approach
225 // would be to use the same approach we use on the file level (no
226 // re-indentation if there was a structural error) within the macro
227 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000228 parseFile();
229}
230
231void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000232 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000233 nextToken();
234 } while (!eof());
235 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000236}
237
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000238void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000239 assert(!FormatTok.Tok.is(tok::l_brace));
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000240 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000241 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000242 case tok::at:
243 nextToken();
244 switch (FormatTok.Tok.getObjCKeywordID()) {
245 case tok::objc_public:
246 case tok::objc_protected:
247 case tok::objc_package:
248 case tok::objc_private:
249 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000250 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000251 case tok::objc_implementation:
252 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000253 case tok::objc_protocol:
254 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000255 case tok::objc_end:
256 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000257 case tok::objc_optional:
258 case tok::objc_required:
259 nextToken();
260 addUnwrappedLine();
261 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000262 default:
263 break;
264 }
265 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000266 case tok::kw_namespace:
267 parseNamespace();
268 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000269 case tok::kw_inline:
270 nextToken();
271 TokenNumber++;
272 if (FormatTok.Tok.is(tok::kw_namespace)) {
273 parseNamespace();
274 return;
275 }
276 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000277 case tok::kw_public:
278 case tok::kw_protected:
279 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000280 parseAccessSpecifier();
281 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000282 case tok::kw_if:
283 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000284 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000285 case tok::kw_for:
286 case tok::kw_while:
287 parseForOrWhileLoop();
288 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000289 case tok::kw_do:
290 parseDoWhile();
291 return;
292 case tok::kw_switch:
293 parseSwitch();
294 return;
295 case tok::kw_default:
296 nextToken();
297 parseLabel();
298 return;
299 case tok::kw_case:
300 parseCaseLabel();
301 return;
Manuel Klimekc44ee892013-01-21 10:07:49 +0000302 case tok::kw_return:
303 parseReturn();
304 return;
Manuel Klimekd19dc2d2013-01-21 14:32:05 +0000305 case tok::kw_extern:
306 nextToken();
307 if (FormatTok.Tok.is(tok::string_literal)) {
308 nextToken();
309 if (FormatTok.Tok.is(tok::l_brace)) {
310 parseBlock(0);
311 addUnwrappedLine();
312 return;
313 }
314 }
315 // In all other cases, parse the declaration.
316 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000317 default:
318 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000319 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000320 do {
321 ++TokenNumber;
322 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000323 case tok::kw_enum:
324 parseEnum();
Manuel Klimek308232c2013-01-21 19:17:52 +0000325 break;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000326 case tok::kw_struct:
327 case tok::kw_union:
Manuel Klimekde768542013-01-07 18:10:23 +0000328 case tok::kw_class:
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000329 parseRecord();
330 // A record declaration or definition is always the start of a structural
331 // element.
332 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000333 case tok::semi:
334 nextToken();
335 addUnwrappedLine();
336 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000337 case tok::r_brace:
338 addUnwrappedLine();
339 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000340 case tok::l_paren:
341 parseParens();
342 break;
343 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000344 // A block outside of parentheses must be the last part of a
345 // structural element.
346 // FIXME: Figure out cases where this is not true, and add projections for
347 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000348 parseBlock();
349 addUnwrappedLine();
350 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000351 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000352 nextToken();
353 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
354 parseLabel();
355 return;
356 }
357 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000358 case tok::equal:
359 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000360 if (FormatTok.Tok.is(tok::l_brace)) {
361 parseBracedList();
362 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000363 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000364 default:
365 nextToken();
366 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000367 }
368 } while (!eof());
369}
370
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000371void UnwrappedLineParser::parseBracedList() {
372 nextToken();
373
374 do {
375 switch (FormatTok.Tok.getKind()) {
376 case tok::l_brace:
377 parseBracedList();
378 break;
379 case tok::r_brace:
380 nextToken();
381 return;
382 default:
383 nextToken();
384 break;
385 }
386 } while (!eof());
387}
388
Manuel Klimekc44ee892013-01-21 10:07:49 +0000389void UnwrappedLineParser::parseReturn() {
390 nextToken();
391
392 do {
393 switch (FormatTok.Tok.getKind()) {
394 case tok::l_brace:
395 parseBracedList();
396 break;
397 case tok::l_paren:
398 parseParens();
399 break;
400 case tok::r_brace:
401 // Assume missing ';'.
402 addUnwrappedLine();
403 return;
404 case tok::semi:
405 nextToken();
406 addUnwrappedLine();
407 return;
408 default:
409 nextToken();
410 break;
411 }
412 } while (!eof());
413}
414
Daniel Jasperbac016b2012-12-03 18:12:45 +0000415void UnwrappedLineParser::parseParens() {
416 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
417 nextToken();
418 do {
419 switch (FormatTok.Tok.getKind()) {
420 case tok::l_paren:
421 parseParens();
422 break;
423 case tok::r_paren:
424 nextToken();
425 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000426 case tok::l_brace:
427 {
428 nextToken();
429 ScopedLineState LineState(*this);
430 Line->Level += 1;
431 parseLevel(/*HasOpeningBrace=*/true);
432 Line->Level -= 1;
433 }
434 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000435 default:
436 nextToken();
437 break;
438 }
439 } while (!eof());
440}
441
442void UnwrappedLineParser::parseIfThenElse() {
443 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
444 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000445 if (FormatTok.Tok.is(tok::l_paren))
446 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000447 bool NeedsUnwrappedLine = false;
448 if (FormatTok.Tok.is(tok::l_brace)) {
449 parseBlock();
450 NeedsUnwrappedLine = true;
451 } else {
452 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000453 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000454 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000455 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000456 }
457 if (FormatTok.Tok.is(tok::kw_else)) {
458 nextToken();
459 if (FormatTok.Tok.is(tok::l_brace)) {
460 parseBlock();
461 addUnwrappedLine();
462 } else if (FormatTok.Tok.is(tok::kw_if)) {
463 parseIfThenElse();
464 } else {
465 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000466 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000467 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000468 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000469 }
470 } else if (NeedsUnwrappedLine) {
471 addUnwrappedLine();
472 }
473}
474
Alexander Kornienko15757312012-12-06 18:03:27 +0000475void UnwrappedLineParser::parseNamespace() {
476 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
477 nextToken();
478 if (FormatTok.Tok.is(tok::identifier))
479 nextToken();
480 if (FormatTok.Tok.is(tok::l_brace)) {
481 parseBlock(0);
482 addUnwrappedLine();
483 }
484 // FIXME: Add error handling.
485}
486
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000487void UnwrappedLineParser::parseForOrWhileLoop() {
488 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
489 "'for' or 'while' expected");
490 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000491 if (FormatTok.Tok.is(tok::l_paren))
492 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000493 if (FormatTok.Tok.is(tok::l_brace)) {
494 parseBlock();
495 addUnwrappedLine();
496 } else {
497 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000498 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000499 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000500 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000501 }
502}
503
Daniel Jasperbac016b2012-12-03 18:12:45 +0000504void UnwrappedLineParser::parseDoWhile() {
505 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
506 nextToken();
507 if (FormatTok.Tok.is(tok::l_brace)) {
508 parseBlock();
509 } else {
510 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000511 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000512 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000513 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000514 }
515
Alexander Kornienko393b0082012-12-04 15:40:36 +0000516 // FIXME: Add error handling.
517 if (!FormatTok.Tok.is(tok::kw_while)) {
518 addUnwrappedLine();
519 return;
520 }
521
Daniel Jasperbac016b2012-12-03 18:12:45 +0000522 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000523 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000524}
525
526void UnwrappedLineParser::parseLabel() {
527 // FIXME: remove all asserts.
528 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
529 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000530 unsigned OldLineLevel = Line->Level;
531 if (Line->Level > 0)
532 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000533 if (FormatTok.Tok.is(tok::l_brace)) {
534 parseBlock();
Nico Weber94fb7292013-01-18 05:50:57 +0000535 if (FormatTok.Tok.is(tok::kw_break))
536 parseStructuralElement(); // "break;" after "}" goes on the same line.
Daniel Jasperbac016b2012-12-03 18:12:45 +0000537 }
538 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000539 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000540}
541
542void UnwrappedLineParser::parseCaseLabel() {
543 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
544 // FIXME: fix handling of complex expressions here.
545 do {
546 nextToken();
547 } while (!eof() && !FormatTok.Tok.is(tok::colon));
548 parseLabel();
549}
550
551void UnwrappedLineParser::parseSwitch() {
552 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
553 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000554 if (FormatTok.Tok.is(tok::l_paren))
555 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000556 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000557 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000558 addUnwrappedLine();
559 } else {
560 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000561 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000562 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000563 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000564 }
565}
566
567void UnwrappedLineParser::parseAccessSpecifier() {
568 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000569 // Otherwise, we don't know what it is, and we'd better keep the next token.
570 if (FormatTok.Tok.is(tok::colon))
571 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000572 addUnwrappedLine();
573}
574
575void UnwrappedLineParser::parseEnum() {
Manuel Klimek308232c2013-01-21 19:17:52 +0000576 nextToken();
577 if (FormatTok.Tok.is(tok::identifier) ||
578 FormatTok.Tok.is(tok::kw___attribute) ||
579 FormatTok.Tok.is(tok::kw___declspec)) {
580 nextToken();
581 // We can have macros or attributes in between 'enum' and the enum name.
582 if (FormatTok.Tok.is(tok::l_paren)) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000583 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000584 }
Manuel Klimek308232c2013-01-21 19:17:52 +0000585 if (FormatTok.Tok.is(tok::identifier))
586 nextToken();
587 }
588 if (FormatTok.Tok.is(tok::l_brace)) {
589 nextToken();
590 addUnwrappedLine();
591 ++Line->Level;
592 do {
593 switch (FormatTok.Tok.getKind()) {
Manuel Klimek308232c2013-01-21 19:17:52 +0000594 case tok::l_paren:
595 parseParens();
596 break;
597 case tok::r_brace:
598 addUnwrappedLine();
599 nextToken();
600 --Line->Level;
601 return;
602 case tok::comma:
603 nextToken();
604 addUnwrappedLine();
605 break;
606 default:
607 nextToken();
608 break;
609 }
610 } while (!eof());
611 }
612 // We fall through to parsing a structural element afterwards, so that in
613 // enum A {} n, m;
614 // "} n, m;" will end up in one unwrapped line.
Daniel Jasperbac016b2012-12-03 18:12:45 +0000615}
616
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000617void UnwrappedLineParser::parseRecord() {
Manuel Klimekde768542013-01-07 18:10:23 +0000618 nextToken();
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000619 if (FormatTok.Tok.is(tok::identifier) ||
620 FormatTok.Tok.is(tok::kw___attribute) ||
621 FormatTok.Tok.is(tok::kw___declspec)) {
622 nextToken();
623 // We can have macros or attributes in between 'class' and the class name.
624 if (FormatTok.Tok.is(tok::l_paren)) {
625 parseParens();
Manuel Klimekde768542013-01-07 18:10:23 +0000626 }
Manuel Klimek7f5b0252013-01-21 10:17:14 +0000627 // The actual identifier can be a nested name specifier.
628 while (FormatTok.Tok.is(tok::identifier) ||
629 FormatTok.Tok.is(tok::coloncolon))
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000630 nextToken();
631
Manuel Klimek3a3408c2013-01-21 13:58:54 +0000632 // Note that parsing away template declarations here leads to incorrectly
633 // accepting function declarations as record declarations.
634 // In general, we cannot solve this problem. Consider:
635 // class A<int> B() {}
636 // which can be a function definition or a class definition when B() is a
637 // macro. If we find enough real-world cases where this is a problem, we
638 // can parse for the 'template' keyword in the beginning of the statement,
639 // and thus rule out the record production in case there is no template
640 // (this would still leave us with an ambiguity between template function
641 // and class declarations).
642 if (FormatTok.Tok.is(tok::colon) || FormatTok.Tok.is(tok::less)) {
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000643 while (FormatTok.Tok.isNot(tok::l_brace)) {
644 if (FormatTok.Tok.is(tok::semi))
645 return;
646 nextToken();
647 }
648 }
649 }
650 if (FormatTok.Tok.is(tok::l_brace))
651 parseBlock();
Manuel Klimek3a3408c2013-01-21 13:58:54 +0000652 // We fall through to parsing a structural element afterwards, so
653 // class A {} n, m;
654 // will end up in one unwrapped line.
Manuel Klimekde768542013-01-07 18:10:23 +0000655}
656
Nico Weber1abe6ea2013-01-09 21:15:03 +0000657void UnwrappedLineParser::parseObjCProtocolList() {
658 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
659 do
660 nextToken();
661 while (!eof() && FormatTok.Tok.isNot(tok::greater));
662 nextToken(); // Skip '>'.
663}
664
665void UnwrappedLineParser::parseObjCUntilAtEnd() {
666 do {
667 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
668 nextToken();
669 addUnwrappedLine();
670 break;
671 }
672 parseStructuralElement();
673 } while (!eof());
674}
675
Nico Weber50767d82013-01-09 23:25:37 +0000676void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000677 nextToken();
678 nextToken(); // interface name
679
680 // @interface can be followed by either a base class, or a category.
681 if (FormatTok.Tok.is(tok::colon)) {
682 nextToken();
683 nextToken(); // base class name
684 } else if (FormatTok.Tok.is(tok::l_paren))
685 // Skip category, if present.
686 parseParens();
687
Nico Weber1abe6ea2013-01-09 21:15:03 +0000688 if (FormatTok.Tok.is(tok::less))
689 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000690
691 // If instance variables are present, keep the '{' on the first line too.
692 if (FormatTok.Tok.is(tok::l_brace))
693 parseBlock();
694
695 // With instance variables, this puts '}' on its own line. Without instance
696 // variables, this ends the @interface line.
697 addUnwrappedLine();
698
Nico Weber1abe6ea2013-01-09 21:15:03 +0000699 parseObjCUntilAtEnd();
700}
Nico Weber27d13672013-01-09 20:25:35 +0000701
Nico Weber1abe6ea2013-01-09 21:15:03 +0000702void UnwrappedLineParser::parseObjCProtocol() {
703 nextToken();
704 nextToken(); // protocol name
705
706 if (FormatTok.Tok.is(tok::less))
707 parseObjCProtocolList();
708
709 // Check for protocol declaration.
710 if (FormatTok.Tok.is(tok::semi)) {
711 nextToken();
712 return addUnwrappedLine();
713 }
714
715 addUnwrappedLine();
716 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000717}
718
Daniel Jasperbac016b2012-12-03 18:12:45 +0000719void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000720 if (Line->Tokens.empty())
Daniel Jasper26f7e782013-01-08 14:56:18 +0000721 return;
Manuel Klimek8fa37992013-01-16 12:31:12 +0000722 DEBUG({
Manuel Klimek86721d22013-01-22 16:31:55 +0000723 llvm::dbgs() << "Line(" << Line->Level << "): ";
Manuel Klimek8fa37992013-01-16 12:31:12 +0000724 for (std::list<FormatToken>::iterator I = Line->Tokens.begin(),
725 E = Line->Tokens.end();
726 I != E; ++I) {
727 llvm::dbgs() << I->Tok.getName() << " ";
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000728
Manuel Klimek8fa37992013-01-16 12:31:12 +0000729 }
730 llvm::dbgs() << "\n";
731 });
Manuel Klimek525fe162013-01-18 14:04:34 +0000732 CurrentLines->push_back(*Line);
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000733 Line->Tokens.clear();
Manuel Klimek525fe162013-01-18 14:04:34 +0000734 if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) {
735 for (std::vector<UnwrappedLine>::iterator I = PreprocessorDirectives
736 .begin(), E = PreprocessorDirectives.end();
737 I != E; ++I) {
738 CurrentLines->push_back(*I);
739 }
740 PreprocessorDirectives.clear();
741 }
742
Daniel Jasperbac016b2012-12-03 18:12:45 +0000743}
744
745bool UnwrappedLineParser::eof() const {
746 return FormatTok.Tok.is(tok::eof);
747}
748
Manuel Klimek86721d22013-01-22 16:31:55 +0000749void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) {
750 bool JustComments = Line->Tokens.empty();
751 for (SmallVectorImpl<FormatToken>::const_iterator
752 I = CommentsBeforeNextToken.begin(),
753 E = CommentsBeforeNextToken.end();
754 I != E; ++I) {
755 if (I->HasUnescapedNewline && JustComments) {
756 addUnwrappedLine();
757 }
758 pushToken(*I);
759 }
760 if (NewlineBeforeNext && JustComments) {
761 addUnwrappedLine();
762 }
763 CommentsBeforeNextToken.clear();
764}
765
Daniel Jasperbac016b2012-12-03 18:12:45 +0000766void UnwrappedLineParser::nextToken() {
767 if (eof())
768 return;
Manuel Klimek86721d22013-01-22 16:31:55 +0000769 flushComments(FormatTok.HasUnescapedNewline);
770 pushToken(FormatTok);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000771 readToken();
772}
773
774void UnwrappedLineParser::readToken() {
Manuel Klimek86721d22013-01-22 16:31:55 +0000775 bool CommentsInCurrentLine = true;
776 do {
777 FormatTok = Tokens->getNextToken();
778 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
779 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
780 FormatTok.IsFirst)) {
781 // If there is an unfinished unwrapped line, we flush the preprocessor
782 // directives only after that unwrapped line was finished later.
783 bool SwitchToPreprocessorLines = !Line->Tokens.empty() &&
784 CurrentLines == &Lines;
785 ScopedLineState BlockState(*this, SwitchToPreprocessorLines);
786 parsePPDirective();
787 }
788 if (!FormatTok.Tok.is(tok::comment))
789 return;
790 if (FormatTok.HasUnescapedNewline || FormatTok.IsFirst) {
791 CommentsInCurrentLine = false;
792 }
793 if (CommentsInCurrentLine) {
794 pushToken(FormatTok);
795 } else {
796 CommentsBeforeNextToken.push_back(FormatTok);
797 }
798 } while (!eof());
799}
800
801void UnwrappedLineParser::pushToken(const FormatToken &Tok) {
802 Line->Tokens.push_back(Tok);
803 if (MustBreakBeforeNextToken) {
804 Line->Tokens.back().MustBreakBefore = true;
805 MustBreakBeforeNextToken = false;
Manuel Klimekd4397b92013-01-04 23:34:14 +0000806 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000807}
808
Daniel Jaspercd162382013-01-07 13:26:07 +0000809} // end namespace format
810} // end namespace clang