blob: d6c66dc9ac452c92af70cd407effe407857cf847 [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();
Daniel Jaspercbb6c412013-01-16 09:10:19 +000084 Parser.Line.reset(new UnwrappedLine());
85 Parser.Line->Level = PreBlockLine->Level;
86 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
Manuel Klimekbb42bf12013-01-10 11:52:21 +000087 }
88
89 ~ScopedLineState() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +000090 if (!Parser.Line->Tokens.empty()) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +000091 Parser.addUnwrappedLine();
92 }
Daniel Jaspercbb6c412013-01-16 09:10:19 +000093 assert(Parser.Line->Tokens.empty());
Manuel Klimekbb42bf12013-01-10 11:52:21 +000094 Parser.Line.reset(PreBlockLine);
Manuel Klimekbb42bf12013-01-10 11:52:21 +000095 Parser.MustBreakBeforeNextToken = true;
96 }
97
98private:
99 UnwrappedLineParser &Parser;
100
101 UnwrappedLine *PreBlockLine;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000102};
103
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000104UnwrappedLineParser::UnwrappedLineParser(
105 clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
106 FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback)
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000107 : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), Diag(Diag),
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000108 Style(Style), Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000109}
110
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000111bool UnwrappedLineParser::parse() {
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000112#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
113 llvm::errs() << "----\n";
114#endif
Manuel Klimekd4397b92013-01-04 23:34:14 +0000115 readToken();
116 return parseFile();
117}
118
119bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +0000120 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000121 // Make sure to format the remaining tokens.
122 addUnwrappedLine();
123 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000124}
125
Manuel Klimeka5342db2013-01-06 20:07:31 +0000126bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000127 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000128 do {
129 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000130 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000131 nextToken();
132 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000133 break;
134 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000135 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000136 addUnwrappedLine();
137 break;
138 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000139 if (HasOpeningBrace) {
140 return false;
141 } else {
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000142 Diag.Report(FormatTok.Tok.getLocation(),
143 Diag.getCustomDiagID(clang::DiagnosticsEngine::Error,
Alexander Kornienko276a2092013-01-11 16:03:45 +0000144 "unexpected '}'"));
Manuel Klimeka5342db2013-01-06 20:07:31 +0000145 Error = true;
146 nextToken();
147 addUnwrappedLine();
148 }
149 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000150 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000151 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000152 break;
153 }
154 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000155 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000156}
157
Alexander Kornienko15757312012-12-06 18:03:27 +0000158bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000159 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000160 nextToken();
161
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000162 if (!FormatTok.Tok.is(tok::r_brace)) {
163 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000164
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000165 Line->Level += AddLevels;
166 parseLevel(/*HasOpeningBrace=*/true);
167 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000168
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000169 if (!FormatTok.Tok.is(tok::r_brace))
170 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000171
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000172 }
Manuel Klimekde768542013-01-07 18:10:23 +0000173 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000174 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000175}
176
177void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000178 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000179 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000180 nextToken();
181
Manuel Klimeka080a182013-01-02 16:30:12 +0000182 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
183 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000184 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000185 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000186
Manuel Klimekd4397b92013-01-04 23:34:14 +0000187 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
188 case tok::pp_define:
189 parsePPDefine();
190 break;
191 default:
192 parsePPUnknown();
193 break;
194 }
195}
196
197void UnwrappedLineParser::parsePPDefine() {
198 nextToken();
199
200 if (FormatTok.Tok.getKind() != tok::identifier) {
201 parsePPUnknown();
202 return;
203 }
204 nextToken();
205 if (FormatTok.Tok.getKind() == tok::l_paren) {
206 parseParens();
207 }
208 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000209 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000210
211 // Errors during a preprocessor directive can only affect the layout of the
212 // preprocessor directive, and thus we ignore them. An alternative approach
213 // would be to use the same approach we use on the file level (no
214 // re-indentation if there was a structural error) within the macro
215 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000216 parseFile();
217}
218
219void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000220 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000221 nextToken();
222 } while (!eof());
223 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000224}
225
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000226void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000227 // Consume leading line comments, e.g. for branches without compounds.
228 while (FormatTok.Tok.is(tok::comment)) {
229 nextToken();
230 addUnwrappedLine();
231 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000232}
233
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000234void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000235 assert(!FormatTok.Tok.is(tok::l_brace));
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000236 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000237
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000238 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000239 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000240 case tok::at:
241 nextToken();
242 switch (FormatTok.Tok.getObjCKeywordID()) {
243 case tok::objc_public:
244 case tok::objc_protected:
245 case tok::objc_package:
246 case tok::objc_private:
247 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000248 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000249 case tok::objc_implementation:
250 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000251 case tok::objc_protocol:
252 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000253 case tok::objc_end:
254 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000255 case tok::objc_optional:
256 case tok::objc_required:
257 nextToken();
258 addUnwrappedLine();
259 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000260 default:
261 break;
262 }
263 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000264 case tok::kw_namespace:
265 parseNamespace();
266 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000267 case tok::kw_inline:
268 nextToken();
269 TokenNumber++;
270 if (FormatTok.Tok.is(tok::kw_namespace)) {
271 parseNamespace();
272 return;
273 }
274 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000275 case tok::kw_public:
276 case tok::kw_protected:
277 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000278 parseAccessSpecifier();
279 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000280 case tok::kw_if:
281 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000282 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000283 case tok::kw_for:
284 case tok::kw_while:
285 parseForOrWhileLoop();
286 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000287 case tok::kw_do:
288 parseDoWhile();
289 return;
290 case tok::kw_switch:
291 parseSwitch();
292 return;
293 case tok::kw_default:
294 nextToken();
295 parseLabel();
296 return;
297 case tok::kw_case:
298 parseCaseLabel();
299 return;
300 default:
301 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000302 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000303 do {
304 ++TokenNumber;
305 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000306 case tok::kw_enum:
307 parseEnum();
308 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000309 case tok::kw_struct:
310 case tok::kw_union:
Manuel Klimekde768542013-01-07 18:10:23 +0000311 case tok::kw_class:
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000312 parseRecord();
313 // A record declaration or definition is always the start of a structural
314 // element.
315 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000316 case tok::semi:
317 nextToken();
318 addUnwrappedLine();
319 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000320 case tok::r_brace:
321 addUnwrappedLine();
322 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000323 case tok::l_paren:
324 parseParens();
325 break;
326 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000327 // A block outside of parentheses must be the last part of a
328 // structural element.
329 // FIXME: Figure out cases where this is not true, and add projections for
330 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000331 parseBlock();
332 addUnwrappedLine();
333 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000334 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000335 nextToken();
336 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
337 parseLabel();
338 return;
339 }
340 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000341 case tok::equal:
342 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000343 if (FormatTok.Tok.is(tok::l_brace)) {
344 parseBracedList();
345 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000346 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000347 default:
348 nextToken();
349 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000350 }
351 } while (!eof());
352}
353
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000354void UnwrappedLineParser::parseBracedList() {
355 nextToken();
356
357 do {
358 switch (FormatTok.Tok.getKind()) {
359 case tok::l_brace:
360 parseBracedList();
361 break;
362 case tok::r_brace:
363 nextToken();
364 return;
365 default:
366 nextToken();
367 break;
368 }
369 } while (!eof());
370}
371
Daniel Jasperbac016b2012-12-03 18:12:45 +0000372void UnwrappedLineParser::parseParens() {
373 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
374 nextToken();
375 do {
376 switch (FormatTok.Tok.getKind()) {
377 case tok::l_paren:
378 parseParens();
379 break;
380 case tok::r_paren:
381 nextToken();
382 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000383 case tok::l_brace:
384 {
385 nextToken();
386 ScopedLineState LineState(*this);
387 Line->Level += 1;
388 parseLevel(/*HasOpeningBrace=*/true);
389 Line->Level -= 1;
390 }
391 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000392 default:
393 nextToken();
394 break;
395 }
396 } while (!eof());
397}
398
399void UnwrappedLineParser::parseIfThenElse() {
400 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
401 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000402 if (FormatTok.Tok.is(tok::l_paren))
403 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000404 bool NeedsUnwrappedLine = false;
405 if (FormatTok.Tok.is(tok::l_brace)) {
406 parseBlock();
407 NeedsUnwrappedLine = true;
408 } else {
409 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000410 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000411 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000412 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000413 }
414 if (FormatTok.Tok.is(tok::kw_else)) {
415 nextToken();
416 if (FormatTok.Tok.is(tok::l_brace)) {
417 parseBlock();
418 addUnwrappedLine();
419 } else if (FormatTok.Tok.is(tok::kw_if)) {
420 parseIfThenElse();
421 } else {
422 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000423 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000424 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000425 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000426 }
427 } else if (NeedsUnwrappedLine) {
428 addUnwrappedLine();
429 }
430}
431
Alexander Kornienko15757312012-12-06 18:03:27 +0000432void UnwrappedLineParser::parseNamespace() {
433 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
434 nextToken();
435 if (FormatTok.Tok.is(tok::identifier))
436 nextToken();
437 if (FormatTok.Tok.is(tok::l_brace)) {
438 parseBlock(0);
439 addUnwrappedLine();
440 }
441 // FIXME: Add error handling.
442}
443
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000444void UnwrappedLineParser::parseForOrWhileLoop() {
445 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
446 "'for' or 'while' expected");
447 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000448 if (FormatTok.Tok.is(tok::l_paren))
449 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000450 if (FormatTok.Tok.is(tok::l_brace)) {
451 parseBlock();
452 addUnwrappedLine();
453 } else {
454 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000455 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000456 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000457 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000458 }
459}
460
Daniel Jasperbac016b2012-12-03 18:12:45 +0000461void UnwrappedLineParser::parseDoWhile() {
462 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
463 nextToken();
464 if (FormatTok.Tok.is(tok::l_brace)) {
465 parseBlock();
466 } else {
467 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000468 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000469 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000470 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000471 }
472
Alexander Kornienko393b0082012-12-04 15:40:36 +0000473 // FIXME: Add error handling.
474 if (!FormatTok.Tok.is(tok::kw_while)) {
475 addUnwrappedLine();
476 return;
477 }
478
Daniel Jasperbac016b2012-12-03 18:12:45 +0000479 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000480 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000481}
482
483void UnwrappedLineParser::parseLabel() {
484 // FIXME: remove all asserts.
485 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
486 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000487 unsigned OldLineLevel = Line->Level;
488 if (Line->Level > 0)
489 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000490 if (FormatTok.Tok.is(tok::l_brace)) {
491 parseBlock();
492 }
493 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000494 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000495}
496
497void UnwrappedLineParser::parseCaseLabel() {
498 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
499 // FIXME: fix handling of complex expressions here.
500 do {
501 nextToken();
502 } while (!eof() && !FormatTok.Tok.is(tok::colon));
503 parseLabel();
504}
505
506void UnwrappedLineParser::parseSwitch() {
507 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
508 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000509 if (FormatTok.Tok.is(tok::l_paren))
510 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000511 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000512 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000513 addUnwrappedLine();
514 } else {
515 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000516 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000517 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000518 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000519 }
520}
521
522void UnwrappedLineParser::parseAccessSpecifier() {
523 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000524 // Otherwise, we don't know what it is, and we'd better keep the next token.
525 if (FormatTok.Tok.is(tok::colon))
526 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000527 addUnwrappedLine();
528}
529
530void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000531 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000532 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000533 switch (FormatTok.Tok.getKind()) {
534 case tok::l_brace:
535 nextToken();
536 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000537 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000538 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000539 break;
540 case tok::l_paren:
541 parseParens();
542 break;
543 case tok::comma:
544 nextToken();
545 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000546 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000547 break;
548 case tok::r_brace:
549 if (HasContents)
550 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000551 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000552 nextToken();
553 break;
554 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000555 nextToken();
556 addUnwrappedLine();
557 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000558 default:
559 HasContents = true;
560 nextToken();
561 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000562 }
563 } while (!eof());
564}
565
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000566void UnwrappedLineParser::parseRecord() {
Manuel Klimekde768542013-01-07 18:10:23 +0000567 nextToken();
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000568 if (FormatTok.Tok.is(tok::identifier) ||
569 FormatTok.Tok.is(tok::kw___attribute) ||
570 FormatTok.Tok.is(tok::kw___declspec)) {
571 nextToken();
572 // We can have macros or attributes in between 'class' and the class name.
573 if (FormatTok.Tok.is(tok::l_paren)) {
574 parseParens();
Manuel Klimekde768542013-01-07 18:10:23 +0000575 }
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000576 if (FormatTok.Tok.is(tok::identifier))
577 nextToken();
578
579 if (FormatTok.Tok.is(tok::colon)) {
580 while (FormatTok.Tok.isNot(tok::l_brace)) {
581 if (FormatTok.Tok.is(tok::semi))
582 return;
583 nextToken();
584 }
585 }
586 }
587 if (FormatTok.Tok.is(tok::l_brace))
588 parseBlock();
Manuel Klimekde768542013-01-07 18:10:23 +0000589}
590
Nico Weber1abe6ea2013-01-09 21:15:03 +0000591void UnwrappedLineParser::parseObjCProtocolList() {
592 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
593 do
594 nextToken();
595 while (!eof() && FormatTok.Tok.isNot(tok::greater));
596 nextToken(); // Skip '>'.
597}
598
599void UnwrappedLineParser::parseObjCUntilAtEnd() {
600 do {
601 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
602 nextToken();
603 addUnwrappedLine();
604 break;
605 }
606 parseStructuralElement();
607 } while (!eof());
608}
609
Nico Weber50767d82013-01-09 23:25:37 +0000610void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000611 nextToken();
612 nextToken(); // interface name
613
614 // @interface can be followed by either a base class, or a category.
615 if (FormatTok.Tok.is(tok::colon)) {
616 nextToken();
617 nextToken(); // base class name
618 } else if (FormatTok.Tok.is(tok::l_paren))
619 // Skip category, if present.
620 parseParens();
621
Nico Weber1abe6ea2013-01-09 21:15:03 +0000622 if (FormatTok.Tok.is(tok::less))
623 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000624
625 // If instance variables are present, keep the '{' on the first line too.
626 if (FormatTok.Tok.is(tok::l_brace))
627 parseBlock();
628
629 // With instance variables, this puts '}' on its own line. Without instance
630 // variables, this ends the @interface line.
631 addUnwrappedLine();
632
Nico Weber1abe6ea2013-01-09 21:15:03 +0000633 parseObjCUntilAtEnd();
634}
Nico Weber27d13672013-01-09 20:25:35 +0000635
Nico Weber1abe6ea2013-01-09 21:15:03 +0000636void UnwrappedLineParser::parseObjCProtocol() {
637 nextToken();
638 nextToken(); // protocol name
639
640 if (FormatTok.Tok.is(tok::less))
641 parseObjCProtocolList();
642
643 // Check for protocol declaration.
644 if (FormatTok.Tok.is(tok::semi)) {
645 nextToken();
646 return addUnwrappedLine();
647 }
648
649 addUnwrappedLine();
650 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000651}
652
Daniel Jasperbac016b2012-12-03 18:12:45 +0000653void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000654 if (Line->Tokens.empty())
Daniel Jasper26f7e782013-01-08 14:56:18 +0000655 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000656 // Consume trailing comments.
657 while (!eof() && FormatTok.NewlinesBefore == 0 &&
658 FormatTok.Tok.is(tok::comment)) {
659 nextToken();
660 }
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000661#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000662 llvm::errs() << "Line: ";
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000663 for (std::list<FormatToken>::iterator I = Line->Tokens.begin(),
664 E = Line->Tokens.end();
665 I != E; ++I) {
666 llvm::errs() << I->Tok.getName() << " ";
667
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000668 }
669 llvm::errs() << "\n";
670#endif
Manuel Klimek526ed112013-01-09 15:25:02 +0000671 Callback.consumeUnwrappedLine(*Line);
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000672 Line->Tokens.clear();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000673}
674
675bool UnwrappedLineParser::eof() const {
676 return FormatTok.Tok.is(tok::eof);
677}
678
679void UnwrappedLineParser::nextToken() {
680 if (eof())
681 return;
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000682 Line->Tokens.push_back(FormatTok);
Manuel Klimek526ed112013-01-09 15:25:02 +0000683 if (MustBreakBeforeNextToken) {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000684 Line->Tokens.back().MustBreakBefore = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000685 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000686 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000687 readToken();
688}
689
690void UnwrappedLineParser::readToken() {
691 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000692 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000693 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
694 FormatTok.IsFirst)) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000695 ScopedLineState BlockState(*this);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000696 parsePPDirective();
697 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000698}
699
Daniel Jaspercd162382013-01-07 13:26:07 +0000700} // end namespace format
701} // end namespace clang