blob: 1f71b5b7dacc472bcec6411a198d5c6a31b4ac55 [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
Manuel Klimek8fa37992013-01-16 12:31:12 +000021#include "clang/Basic/Diagnostic.h"
22#include "llvm/Support/Debug.h"
Manuel Klimek8fa37992013-01-16 12:31:12 +000023#include "UnwrappedLineParser.h"
24
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:
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 Klimek8fa37992013-01-16 12:31:12 +0000112 DEBUG(llvm::dbgs() << "----\n");
Manuel Klimekd4397b92013-01-04 23:34:14 +0000113 readToken();
114 return parseFile();
115}
116
117bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +0000118 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000119 // Make sure to format the remaining tokens.
120 addUnwrappedLine();
121 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000122}
123
Manuel Klimeka5342db2013-01-06 20:07:31 +0000124bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000125 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000126 do {
127 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000128 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000129 nextToken();
130 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000131 break;
132 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000133 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000134 addUnwrappedLine();
135 break;
136 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000137 if (HasOpeningBrace) {
138 return false;
139 } else {
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000140 Diag.Report(FormatTok.Tok.getLocation(),
141 Diag.getCustomDiagID(clang::DiagnosticsEngine::Error,
Alexander Kornienko276a2092013-01-11 16:03:45 +0000142 "unexpected '}'"));
Manuel Klimeka5342db2013-01-06 20:07:31 +0000143 Error = true;
144 nextToken();
145 addUnwrappedLine();
146 }
147 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000148 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000149 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000150 break;
151 }
152 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000153 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000154}
155
Alexander Kornienko15757312012-12-06 18:03:27 +0000156bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000157 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000158 nextToken();
159
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000160 if (!FormatTok.Tok.is(tok::r_brace)) {
161 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000162
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000163 Line->Level += AddLevels;
164 parseLevel(/*HasOpeningBrace=*/true);
165 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000166
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000167 if (!FormatTok.Tok.is(tok::r_brace))
168 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000169
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000170 }
Manuel Klimekde768542013-01-07 18:10:23 +0000171 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000172 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000173}
174
175void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000176 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000177 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000178 nextToken();
179
Manuel Klimeka080a182013-01-02 16:30:12 +0000180 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
181 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000182 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000183 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000184
Manuel Klimekd4397b92013-01-04 23:34:14 +0000185 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
186 case tok::pp_define:
187 parsePPDefine();
188 break;
189 default:
190 parsePPUnknown();
191 break;
192 }
193}
194
195void UnwrappedLineParser::parsePPDefine() {
196 nextToken();
197
198 if (FormatTok.Tok.getKind() != tok::identifier) {
199 parsePPUnknown();
200 return;
201 }
202 nextToken();
203 if (FormatTok.Tok.getKind() == tok::l_paren) {
204 parseParens();
205 }
206 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000207 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000208
209 // Errors during a preprocessor directive can only affect the layout of the
210 // preprocessor directive, and thus we ignore them. An alternative approach
211 // would be to use the same approach we use on the file level (no
212 // re-indentation if there was a structural error) within the macro
213 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000214 parseFile();
215}
216
217void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000218 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000219 nextToken();
220 } while (!eof());
221 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000222}
223
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000224void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000225 // Consume leading line comments, e.g. for branches without compounds.
226 while (FormatTok.Tok.is(tok::comment)) {
227 nextToken();
228 addUnwrappedLine();
229 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000230}
231
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000232void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000233 assert(!FormatTok.Tok.is(tok::l_brace));
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000234 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000235
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000236 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000237 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000238 case tok::at:
239 nextToken();
240 switch (FormatTok.Tok.getObjCKeywordID()) {
241 case tok::objc_public:
242 case tok::objc_protected:
243 case tok::objc_package:
244 case tok::objc_private:
245 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000246 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000247 case tok::objc_implementation:
248 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000249 case tok::objc_protocol:
250 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000251 case tok::objc_end:
252 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000253 case tok::objc_optional:
254 case tok::objc_required:
255 nextToken();
256 addUnwrappedLine();
257 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000258 default:
259 break;
260 }
261 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000262 case tok::kw_namespace:
263 parseNamespace();
264 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000265 case tok::kw_inline:
266 nextToken();
267 TokenNumber++;
268 if (FormatTok.Tok.is(tok::kw_namespace)) {
269 parseNamespace();
270 return;
271 }
272 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000273 case tok::kw_public:
274 case tok::kw_protected:
275 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000276 parseAccessSpecifier();
277 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000278 case tok::kw_if:
279 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000280 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000281 case tok::kw_for:
282 case tok::kw_while:
283 parseForOrWhileLoop();
284 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000285 case tok::kw_do:
286 parseDoWhile();
287 return;
288 case tok::kw_switch:
289 parseSwitch();
290 return;
291 case tok::kw_default:
292 nextToken();
293 parseLabel();
294 return;
295 case tok::kw_case:
296 parseCaseLabel();
297 return;
298 default:
299 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000300 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000301 do {
302 ++TokenNumber;
303 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000304 case tok::kw_enum:
305 parseEnum();
306 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000307 case tok::kw_struct:
308 case tok::kw_union:
Manuel Klimekde768542013-01-07 18:10:23 +0000309 case tok::kw_class:
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000310 parseRecord();
311 // A record declaration or definition is always the start of a structural
312 // element.
313 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000314 case tok::semi:
315 nextToken();
316 addUnwrappedLine();
317 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000318 case tok::r_brace:
319 addUnwrappedLine();
320 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000321 case tok::l_paren:
322 parseParens();
323 break;
324 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000325 // A block outside of parentheses must be the last part of a
326 // structural element.
327 // FIXME: Figure out cases where this is not true, and add projections for
328 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000329 parseBlock();
330 addUnwrappedLine();
331 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000332 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000333 nextToken();
334 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
335 parseLabel();
336 return;
337 }
338 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000339 case tok::equal:
340 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000341 if (FormatTok.Tok.is(tok::l_brace)) {
342 parseBracedList();
343 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000344 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000345 default:
346 nextToken();
347 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000348 }
349 } while (!eof());
350}
351
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000352void UnwrappedLineParser::parseBracedList() {
353 nextToken();
354
355 do {
356 switch (FormatTok.Tok.getKind()) {
357 case tok::l_brace:
358 parseBracedList();
359 break;
360 case tok::r_brace:
361 nextToken();
362 return;
363 default:
364 nextToken();
365 break;
366 }
367 } while (!eof());
368}
369
Daniel Jasperbac016b2012-12-03 18:12:45 +0000370void UnwrappedLineParser::parseParens() {
371 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
372 nextToken();
373 do {
374 switch (FormatTok.Tok.getKind()) {
375 case tok::l_paren:
376 parseParens();
377 break;
378 case tok::r_paren:
379 nextToken();
380 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000381 case tok::l_brace:
382 {
383 nextToken();
384 ScopedLineState LineState(*this);
385 Line->Level += 1;
386 parseLevel(/*HasOpeningBrace=*/true);
387 Line->Level -= 1;
388 }
389 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000390 default:
391 nextToken();
392 break;
393 }
394 } while (!eof());
395}
396
397void UnwrappedLineParser::parseIfThenElse() {
398 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
399 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000400 if (FormatTok.Tok.is(tok::l_paren))
401 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000402 bool NeedsUnwrappedLine = false;
403 if (FormatTok.Tok.is(tok::l_brace)) {
404 parseBlock();
405 NeedsUnwrappedLine = true;
406 } else {
407 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000408 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000409 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000410 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000411 }
412 if (FormatTok.Tok.is(tok::kw_else)) {
413 nextToken();
414 if (FormatTok.Tok.is(tok::l_brace)) {
415 parseBlock();
416 addUnwrappedLine();
417 } else if (FormatTok.Tok.is(tok::kw_if)) {
418 parseIfThenElse();
419 } else {
420 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000421 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000422 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000423 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000424 }
425 } else if (NeedsUnwrappedLine) {
426 addUnwrappedLine();
427 }
428}
429
Alexander Kornienko15757312012-12-06 18:03:27 +0000430void UnwrappedLineParser::parseNamespace() {
431 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
432 nextToken();
433 if (FormatTok.Tok.is(tok::identifier))
434 nextToken();
435 if (FormatTok.Tok.is(tok::l_brace)) {
436 parseBlock(0);
437 addUnwrappedLine();
438 }
439 // FIXME: Add error handling.
440}
441
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000442void UnwrappedLineParser::parseForOrWhileLoop() {
443 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
444 "'for' or 'while' expected");
445 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000446 if (FormatTok.Tok.is(tok::l_paren))
447 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000448 if (FormatTok.Tok.is(tok::l_brace)) {
449 parseBlock();
450 addUnwrappedLine();
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;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000456 }
457}
458
Daniel Jasperbac016b2012-12-03 18:12:45 +0000459void UnwrappedLineParser::parseDoWhile() {
460 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
461 nextToken();
462 if (FormatTok.Tok.is(tok::l_brace)) {
463 parseBlock();
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
Alexander Kornienko393b0082012-12-04 15:40:36 +0000471 // FIXME: Add error handling.
472 if (!FormatTok.Tok.is(tok::kw_while)) {
473 addUnwrappedLine();
474 return;
475 }
476
Daniel Jasperbac016b2012-12-03 18:12:45 +0000477 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000478 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000479}
480
481void UnwrappedLineParser::parseLabel() {
482 // FIXME: remove all asserts.
483 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
484 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000485 unsigned OldLineLevel = Line->Level;
486 if (Line->Level > 0)
487 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000488 if (FormatTok.Tok.is(tok::l_brace)) {
489 parseBlock();
Nico Weber94fb7292013-01-18 05:50:57 +0000490 if (FormatTok.Tok.is(tok::kw_break))
491 parseStructuralElement(); // "break;" after "}" goes on the same line.
Daniel Jasperbac016b2012-12-03 18:12:45 +0000492 }
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 Klimek8fa37992013-01-16 12:31:12 +0000661 DEBUG({
662 llvm::dbgs() << "Line: ";
663 for (std::list<FormatToken>::iterator I = Line->Tokens.begin(),
664 E = Line->Tokens.end();
665 I != E; ++I) {
666 llvm::dbgs() << I->Tok.getName() << " ";
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000667
Manuel Klimek8fa37992013-01-16 12:31:12 +0000668 }
669 llvm::dbgs() << "\n";
670 });
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