blob: a6c5c165ffda030f59ac4c31ea1bae70e0f596d0 [file] [log] [blame]
Daniel Jasperbac016b2012-12-03 18:12:45 +00001//===--- UnwrappedLineParser.cpp - Format C++ code ------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file contains the implementation of the UnwrappedLineParser,
12/// which turns a stream of tokens into UnwrappedLines.
13///
14/// This is EXPERIMENTAL code under heavy development. It is not in a state yet,
15/// where it can be used to format real code.
16///
17//===----------------------------------------------------------------------===//
18
19#include "UnwrappedLineParser.h"
Alexander Kornienko3048aea2013-01-10 15:05:09 +000020#include "clang/Basic/Diagnostic.h"
Daniel Jasperbac016b2012-12-03 18:12:45 +000021#include "llvm/Support/raw_ostream.h"
22
Manuel Klimek4c60fc62013-01-10 10:05:08 +000023// Uncomment to get debug output from the UnwrappedLineParser.
24// Use in combination with --gtest_filter=*TestName* to limit the output to a
25// single test.
26// #define UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
27
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:
82 ScopedLineState(UnwrappedLineParser &Parser) : Parser(Parser) {
83 PreBlockLine = Parser.Line.take();
84 Parser.Line.reset(new UnwrappedLine(*PreBlockLine));
85 assert(Parser.LastInCurrentLine == NULL ||
86 Parser.LastInCurrentLine->Children.empty());
87 PreBlockLastToken = Parser.LastInCurrentLine;
88 PreBlockRootTokenInitialized = Parser.RootTokenInitialized;
89 Parser.RootTokenInitialized = false;
90 Parser.LastInCurrentLine = NULL;
91 }
92
93 ~ScopedLineState() {
94 if (Parser.RootTokenInitialized) {
95 Parser.addUnwrappedLine();
96 }
97 assert(!Parser.RootTokenInitialized);
98 Parser.Line.reset(PreBlockLine);
99 Parser.RootTokenInitialized = PreBlockRootTokenInitialized;
100 Parser.LastInCurrentLine = PreBlockLastToken;
101 assert(Parser.LastInCurrentLine == NULL ||
102 Parser.LastInCurrentLine->Children.empty());
103 Parser.MustBreakBeforeNextToken = true;
104 }
105
106private:
107 UnwrappedLineParser &Parser;
108
109 UnwrappedLine *PreBlockLine;
110 FormatToken* PreBlockLastToken;
111 bool PreBlockRootTokenInitialized;
112};
113
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000114UnwrappedLineParser::UnwrappedLineParser(
115 clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
116 FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback)
Manuel Klimek526ed112013-01-09 15:25:02 +0000117 : Line(new UnwrappedLine), RootTokenInitialized(false),
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000118 LastInCurrentLine(NULL), MustBreakBeforeNextToken(false), Diag(Diag),
119 Style(Style), Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000120}
121
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000122bool UnwrappedLineParser::parse() {
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000123#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
124 llvm::errs() << "----\n";
125#endif
Manuel Klimekd4397b92013-01-04 23:34:14 +0000126 readToken();
127 return parseFile();
128}
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,
155 "Stray '}' found"));
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;
311 default:
312 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000313 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000314 do {
315 ++TokenNumber;
316 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000317 case tok::kw_enum:
318 parseEnum();
319 return;
Manuel Klimekde768542013-01-07 18:10:23 +0000320 case tok::kw_struct: // fallthrough
321 case tok::kw_class:
322 parseStructOrClass();
323 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000324 case tok::semi:
325 nextToken();
326 addUnwrappedLine();
327 return;
328 case tok::l_paren:
329 parseParens();
330 break;
331 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000332 // A block outside of parentheses must be the last part of a
333 // structural element.
334 // FIXME: Figure out cases where this is not true, and add projections for
335 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000336 parseBlock();
337 addUnwrappedLine();
338 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000339 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000340 nextToken();
341 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
342 parseLabel();
343 return;
344 }
345 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000346 case tok::equal:
347 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000348 if (FormatTok.Tok.is(tok::l_brace)) {
349 parseBracedList();
350 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000351 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000352 default:
353 nextToken();
354 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000355 }
356 } while (!eof());
357}
358
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000359void UnwrappedLineParser::parseBracedList() {
360 nextToken();
361
362 do {
363 switch (FormatTok.Tok.getKind()) {
364 case tok::l_brace:
365 parseBracedList();
366 break;
367 case tok::r_brace:
368 nextToken();
369 return;
370 default:
371 nextToken();
372 break;
373 }
374 } while (!eof());
375}
376
Daniel Jasperbac016b2012-12-03 18:12:45 +0000377void UnwrappedLineParser::parseParens() {
378 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
379 nextToken();
380 do {
381 switch (FormatTok.Tok.getKind()) {
382 case tok::l_paren:
383 parseParens();
384 break;
385 case tok::r_paren:
386 nextToken();
387 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000388 case tok::l_brace:
389 {
390 nextToken();
391 ScopedLineState LineState(*this);
392 Line->Level += 1;
393 parseLevel(/*HasOpeningBrace=*/true);
394 Line->Level -= 1;
395 }
396 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000397 default:
398 nextToken();
399 break;
400 }
401 } while (!eof());
402}
403
404void UnwrappedLineParser::parseIfThenElse() {
405 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
406 nextToken();
407 parseParens();
408 bool NeedsUnwrappedLine = false;
409 if (FormatTok.Tok.is(tok::l_brace)) {
410 parseBlock();
411 NeedsUnwrappedLine = true;
412 } else {
413 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000414 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000415 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000416 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000417 }
418 if (FormatTok.Tok.is(tok::kw_else)) {
419 nextToken();
420 if (FormatTok.Tok.is(tok::l_brace)) {
421 parseBlock();
422 addUnwrappedLine();
423 } else if (FormatTok.Tok.is(tok::kw_if)) {
424 parseIfThenElse();
425 } else {
426 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000427 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000428 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000429 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000430 }
431 } else if (NeedsUnwrappedLine) {
432 addUnwrappedLine();
433 }
434}
435
Alexander Kornienko15757312012-12-06 18:03:27 +0000436void UnwrappedLineParser::parseNamespace() {
437 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
438 nextToken();
439 if (FormatTok.Tok.is(tok::identifier))
440 nextToken();
441 if (FormatTok.Tok.is(tok::l_brace)) {
442 parseBlock(0);
443 addUnwrappedLine();
444 }
445 // FIXME: Add error handling.
446}
447
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000448void UnwrappedLineParser::parseForOrWhileLoop() {
449 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
450 "'for' or 'while' expected");
451 nextToken();
452 parseParens();
453 if (FormatTok.Tok.is(tok::l_brace)) {
454 parseBlock();
455 addUnwrappedLine();
456 } else {
457 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000458 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000459 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000460 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000461 }
462}
463
Daniel Jasperbac016b2012-12-03 18:12:45 +0000464void UnwrappedLineParser::parseDoWhile() {
465 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
466 nextToken();
467 if (FormatTok.Tok.is(tok::l_brace)) {
468 parseBlock();
469 } else {
470 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000471 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000472 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000473 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000474 }
475
Alexander Kornienko393b0082012-12-04 15:40:36 +0000476 // FIXME: Add error handling.
477 if (!FormatTok.Tok.is(tok::kw_while)) {
478 addUnwrappedLine();
479 return;
480 }
481
Daniel Jasperbac016b2012-12-03 18:12:45 +0000482 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000483 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000484}
485
486void UnwrappedLineParser::parseLabel() {
487 // FIXME: remove all asserts.
488 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
489 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000490 unsigned OldLineLevel = Line->Level;
491 if (Line->Level > 0)
492 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000493 if (FormatTok.Tok.is(tok::l_brace)) {
494 parseBlock();
495 }
496 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000497 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000498}
499
500void UnwrappedLineParser::parseCaseLabel() {
501 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
502 // FIXME: fix handling of complex expressions here.
503 do {
504 nextToken();
505 } while (!eof() && !FormatTok.Tok.is(tok::colon));
506 parseLabel();
507}
508
509void UnwrappedLineParser::parseSwitch() {
510 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
511 nextToken();
512 parseParens();
513 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000514 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000515 addUnwrappedLine();
516 } else {
517 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000518 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000519 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000520 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000521 }
522}
523
524void UnwrappedLineParser::parseAccessSpecifier() {
525 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000526 // Otherwise, we don't know what it is, and we'd better keep the next token.
527 if (FormatTok.Tok.is(tok::colon))
528 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000529 addUnwrappedLine();
530}
531
532void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000533 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000534 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000535 switch (FormatTok.Tok.getKind()) {
536 case tok::l_brace:
537 nextToken();
538 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000539 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000540 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000541 break;
542 case tok::l_paren:
543 parseParens();
544 break;
545 case tok::comma:
546 nextToken();
547 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000548 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000549 break;
550 case tok::r_brace:
551 if (HasContents)
552 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000553 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000554 nextToken();
555 break;
556 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000557 nextToken();
558 addUnwrappedLine();
559 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000560 default:
561 HasContents = true;
562 nextToken();
563 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000564 }
565 } while (!eof());
566}
567
Manuel Klimekde768542013-01-07 18:10:23 +0000568void UnwrappedLineParser::parseStructOrClass() {
569 nextToken();
570 do {
571 switch (FormatTok.Tok.getKind()) {
572 case tok::l_brace:
573 // FIXME: Think about how to resolve the error handling here.
574 parseBlock();
575 parseStructuralElement();
576 return;
577 case tok::semi:
578 nextToken();
579 addUnwrappedLine();
580 return;
581 default:
582 nextToken();
583 break;
584 }
585 } while (!eof());
586}
587
Nico Weber1abe6ea2013-01-09 21:15:03 +0000588void UnwrappedLineParser::parseObjCProtocolList() {
589 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
590 do
591 nextToken();
592 while (!eof() && FormatTok.Tok.isNot(tok::greater));
593 nextToken(); // Skip '>'.
594}
595
596void UnwrappedLineParser::parseObjCUntilAtEnd() {
597 do {
598 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
599 nextToken();
600 addUnwrappedLine();
601 break;
602 }
603 parseStructuralElement();
604 } while (!eof());
605}
606
Nico Weber50767d82013-01-09 23:25:37 +0000607void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000608 nextToken();
609 nextToken(); // interface name
610
611 // @interface can be followed by either a base class, or a category.
612 if (FormatTok.Tok.is(tok::colon)) {
613 nextToken();
614 nextToken(); // base class name
615 } else if (FormatTok.Tok.is(tok::l_paren))
616 // Skip category, if present.
617 parseParens();
618
Nico Weber1abe6ea2013-01-09 21:15:03 +0000619 if (FormatTok.Tok.is(tok::less))
620 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000621
622 // If instance variables are present, keep the '{' on the first line too.
623 if (FormatTok.Tok.is(tok::l_brace))
624 parseBlock();
625
626 // With instance variables, this puts '}' on its own line. Without instance
627 // variables, this ends the @interface line.
628 addUnwrappedLine();
629
Nico Weber1abe6ea2013-01-09 21:15:03 +0000630 parseObjCUntilAtEnd();
631}
Nico Weber27d13672013-01-09 20:25:35 +0000632
Nico Weber1abe6ea2013-01-09 21:15:03 +0000633void UnwrappedLineParser::parseObjCProtocol() {
634 nextToken();
635 nextToken(); // protocol name
636
637 if (FormatTok.Tok.is(tok::less))
638 parseObjCProtocolList();
639
640 // Check for protocol declaration.
641 if (FormatTok.Tok.is(tok::semi)) {
642 nextToken();
643 return addUnwrappedLine();
644 }
645
646 addUnwrappedLine();
647 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000648}
649
Daniel Jasperbac016b2012-12-03 18:12:45 +0000650void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000651 if (!RootTokenInitialized)
652 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000653 // Consume trailing comments.
654 while (!eof() && FormatTok.NewlinesBefore == 0 &&
655 FormatTok.Tok.is(tok::comment)) {
656 nextToken();
657 }
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000658#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
659 FormatToken* NextToken = &Line->RootToken;
660 llvm::errs() << "Line: ";
661 while (NextToken) {
662 llvm::errs() << NextToken->Tok.getName() << " ";
663 NextToken = NextToken->Children.empty() ? NULL : &NextToken->Children[0];
664 }
665 llvm::errs() << "\n";
666#endif
Manuel Klimek526ed112013-01-09 15:25:02 +0000667 Callback.consumeUnwrappedLine(*Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000668 RootTokenInitialized = false;
Manuel Klimek526ed112013-01-09 15:25:02 +0000669 LastInCurrentLine = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000670}
671
672bool UnwrappedLineParser::eof() const {
673 return FormatTok.Tok.is(tok::eof);
674}
675
676void UnwrappedLineParser::nextToken() {
677 if (eof())
678 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000679 if (RootTokenInitialized) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000680 assert(LastInCurrentLine->Children.empty());
Daniel Jasper26f7e782013-01-08 14:56:18 +0000681 LastInCurrentLine->Children.push_back(FormatTok);
682 LastInCurrentLine = &LastInCurrentLine->Children.back();
683 } else {
Manuel Klimek526ed112013-01-09 15:25:02 +0000684 Line->RootToken = FormatTok;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000685 RootTokenInitialized = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000686 LastInCurrentLine = &Line->RootToken;
687 }
688 if (MustBreakBeforeNextToken) {
689 LastInCurrentLine->MustBreakBefore = true;
690 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000691 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000692 readToken();
693}
694
695void UnwrappedLineParser::readToken() {
696 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000697 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000698 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
699 FormatTok.IsFirst)) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000700 ScopedLineState BlockState(*this);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000701 parsePPDirective();
702 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000703}
704
Daniel Jaspercd162382013-01-07 13:26:07 +0000705} // end namespace format
706} // end namespace clang