blob: 736178e1ebea99ace349841ec15bf38d1c8d5bef [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"
Daniel Jasperbac016b2012-12-03 18:12:45 +000020#include "llvm/Support/raw_ostream.h"
21
Manuel Klimek4c60fc62013-01-10 10:05:08 +000022// Uncomment to get debug output from the UnwrappedLineParser.
23// Use in combination with --gtest_filter=*TestName* to limit the output to a
24// single test.
25// #define UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
26
Daniel Jasperbac016b2012-12-03 18:12:45 +000027namespace clang {
28namespace format {
29
Manuel Klimekd4397b92013-01-04 23:34:14 +000030class ScopedMacroState : public FormatTokenSource {
31public:
32 ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
33 FormatToken &ResetToken)
34 : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
Manuel Klimekc37b4d62013-01-05 22:14:16 +000035 PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource) {
Manuel Klimekd4397b92013-01-04 23:34:14 +000036 TokenSource = this;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000037 Line.Level = 0;
Manuel Klimekd4397b92013-01-04 23:34:14 +000038 Line.InPPDirective = true;
39 }
40
41 ~ScopedMacroState() {
42 TokenSource = PreviousTokenSource;
43 ResetToken = Token;
44 Line.InPPDirective = false;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000045 Line.Level = PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000046 }
47
48 virtual FormatToken getNextToken() {
Manuel Klimekdd5b1012013-01-07 10:03:37 +000049 // The \c UnwrappedLineParser guards against this by never calling
50 // \c getNextToken() after it has encountered the first eof token.
51 assert(!eof());
Manuel Klimekd4397b92013-01-04 23:34:14 +000052 Token = PreviousTokenSource->getNextToken();
53 if (eof())
54 return createEOF();
55 return Token;
56 }
57
58private:
59 bool eof() {
60 return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline;
61 }
62
63 FormatToken createEOF() {
64 FormatToken FormatTok;
65 FormatTok.Tok.startToken();
66 FormatTok.Tok.setKind(tok::eof);
67 return FormatTok;
68 }
69
70 UnwrappedLine &Line;
71 FormatTokenSource *&TokenSource;
72 FormatToken &ResetToken;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000073 unsigned PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000074 FormatTokenSource *PreviousTokenSource;
75
76 FormatToken Token;
77};
78
Manuel Klimekbb42bf12013-01-10 11:52:21 +000079class ScopedLineState {
80public:
81 ScopedLineState(UnwrappedLineParser &Parser) : Parser(Parser) {
82 PreBlockLine = Parser.Line.take();
83 Parser.Line.reset(new UnwrappedLine(*PreBlockLine));
84 assert(Parser.LastInCurrentLine == NULL ||
85 Parser.LastInCurrentLine->Children.empty());
86 PreBlockLastToken = Parser.LastInCurrentLine;
87 PreBlockRootTokenInitialized = Parser.RootTokenInitialized;
88 Parser.RootTokenInitialized = false;
89 Parser.LastInCurrentLine = NULL;
90 }
91
92 ~ScopedLineState() {
93 if (Parser.RootTokenInitialized) {
94 Parser.addUnwrappedLine();
95 }
96 assert(!Parser.RootTokenInitialized);
97 Parser.Line.reset(PreBlockLine);
98 Parser.RootTokenInitialized = PreBlockRootTokenInitialized;
99 Parser.LastInCurrentLine = PreBlockLastToken;
100 assert(Parser.LastInCurrentLine == NULL ||
101 Parser.LastInCurrentLine->Children.empty());
102 Parser.MustBreakBeforeNextToken = true;
103 }
104
105private:
106 UnwrappedLineParser &Parser;
107
108 UnwrappedLine *PreBlockLine;
109 FormatToken* PreBlockLastToken;
110 bool PreBlockRootTokenInitialized;
111};
112
Alexander Kornienko469a21b2012-12-07 16:15:44 +0000113UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
114 FormatTokenSource &Tokens,
Daniel Jasperbac016b2012-12-03 18:12:45 +0000115 UnwrappedLineConsumer &Callback)
Manuel Klimek526ed112013-01-09 15:25:02 +0000116 : Line(new UnwrappedLine), RootTokenInitialized(false),
117 LastInCurrentLine(NULL), MustBreakBeforeNextToken(false), Style(Style),
118 Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000119}
120
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000121bool UnwrappedLineParser::parse() {
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000122#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
123 llvm::errs() << "----\n";
124#endif
Manuel Klimekd4397b92013-01-04 23:34:14 +0000125 readToken();
126 return parseFile();
127}
128
129bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +0000130 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000131 // Make sure to format the remaining tokens.
132 addUnwrappedLine();
133 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000134}
135
Manuel Klimeka5342db2013-01-06 20:07:31 +0000136bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000137 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000138 do {
139 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000140 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000141 nextToken();
142 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000143 break;
144 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000145 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000146 addUnwrappedLine();
147 break;
148 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000149 if (HasOpeningBrace) {
150 return false;
151 } else {
152 // Stray '}' is an error.
153 Error = true;
154 nextToken();
155 addUnwrappedLine();
156 }
157 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000158 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000159 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000160 break;
161 }
162 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000163 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000164}
165
Alexander Kornienko15757312012-12-06 18:03:27 +0000166bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000167 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000168 nextToken();
169
Daniel Jasperbac016b2012-12-03 18:12:45 +0000170 addUnwrappedLine();
171
Manuel Klimek526ed112013-01-09 15:25:02 +0000172 Line->Level += AddLevels;
Manuel Klimeka5342db2013-01-06 20:07:31 +0000173 parseLevel(/*HasOpeningBrace=*/true);
Manuel Klimek526ed112013-01-09 15:25:02 +0000174 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000175
Alexander Kornienko393b0082012-12-04 15:40:36 +0000176 if (!FormatTok.Tok.is(tok::r_brace))
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000177 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000178
Manuel Klimekde768542013-01-07 18:10:23 +0000179 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000180 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000181}
182
183void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000184 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000185 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000186 nextToken();
187
Manuel Klimeka080a182013-01-02 16:30:12 +0000188 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
189 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000190 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000191 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000192
Manuel Klimekd4397b92013-01-04 23:34:14 +0000193 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
194 case tok::pp_define:
195 parsePPDefine();
196 break;
197 default:
198 parsePPUnknown();
199 break;
200 }
201}
202
203void UnwrappedLineParser::parsePPDefine() {
204 nextToken();
205
206 if (FormatTok.Tok.getKind() != tok::identifier) {
207 parsePPUnknown();
208 return;
209 }
210 nextToken();
211 if (FormatTok.Tok.getKind() == tok::l_paren) {
212 parseParens();
213 }
214 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000215 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000216
217 // Errors during a preprocessor directive can only affect the layout of the
218 // preprocessor directive, and thus we ignore them. An alternative approach
219 // would be to use the same approach we use on the file level (no
220 // re-indentation if there was a structural error) within the macro
221 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000222 parseFile();
223}
224
225void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000226 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000227 nextToken();
228 } while (!eof());
229 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000230}
231
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000232void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000233 // Consume leading line comments, e.g. for branches without compounds.
234 while (FormatTok.Tok.is(tok::comment)) {
235 nextToken();
236 addUnwrappedLine();
237 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000238}
239
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000240void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000241 assert(!FormatTok.Tok.is(tok::l_brace));
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000242 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000243
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000244 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000245 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000246 case tok::at:
247 nextToken();
248 switch (FormatTok.Tok.getObjCKeywordID()) {
249 case tok::objc_public:
250 case tok::objc_protected:
251 case tok::objc_package:
252 case tok::objc_private:
253 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000254 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000255 case tok::objc_implementation:
256 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000257 case tok::objc_protocol:
258 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000259 case tok::objc_end:
260 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000261 case tok::objc_optional:
262 case tok::objc_required:
263 nextToken();
264 addUnwrappedLine();
265 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000266 default:
267 break;
268 }
269 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000270 case tok::kw_namespace:
271 parseNamespace();
272 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000273 case tok::kw_inline:
274 nextToken();
275 TokenNumber++;
276 if (FormatTok.Tok.is(tok::kw_namespace)) {
277 parseNamespace();
278 return;
279 }
280 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000281 case tok::kw_public:
282 case tok::kw_protected:
283 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000284 parseAccessSpecifier();
285 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000286 case tok::kw_if:
287 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000288 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000289 case tok::kw_for:
290 case tok::kw_while:
291 parseForOrWhileLoop();
292 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000293 case tok::kw_do:
294 parseDoWhile();
295 return;
296 case tok::kw_switch:
297 parseSwitch();
298 return;
299 case tok::kw_default:
300 nextToken();
301 parseLabel();
302 return;
303 case tok::kw_case:
304 parseCaseLabel();
305 return;
306 default:
307 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000308 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000309 do {
310 ++TokenNumber;
311 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000312 case tok::kw_enum:
313 parseEnum();
314 return;
Manuel Klimekde768542013-01-07 18:10:23 +0000315 case tok::kw_struct: // fallthrough
316 case tok::kw_class:
317 parseStructOrClass();
318 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000319 case tok::semi:
320 nextToken();
321 addUnwrappedLine();
322 return;
323 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();
402 parseParens();
403 bool NeedsUnwrappedLine = false;
404 if (FormatTok.Tok.is(tok::l_brace)) {
405 parseBlock();
406 NeedsUnwrappedLine = true;
407 } else {
408 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000409 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000410 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000411 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000412 }
413 if (FormatTok.Tok.is(tok::kw_else)) {
414 nextToken();
415 if (FormatTok.Tok.is(tok::l_brace)) {
416 parseBlock();
417 addUnwrappedLine();
418 } else if (FormatTok.Tok.is(tok::kw_if)) {
419 parseIfThenElse();
420 } else {
421 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000422 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000423 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000424 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000425 }
426 } else if (NeedsUnwrappedLine) {
427 addUnwrappedLine();
428 }
429}
430
Alexander Kornienko15757312012-12-06 18:03:27 +0000431void UnwrappedLineParser::parseNamespace() {
432 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
433 nextToken();
434 if (FormatTok.Tok.is(tok::identifier))
435 nextToken();
436 if (FormatTok.Tok.is(tok::l_brace)) {
437 parseBlock(0);
438 addUnwrappedLine();
439 }
440 // FIXME: Add error handling.
441}
442
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000443void UnwrappedLineParser::parseForOrWhileLoop() {
444 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
445 "'for' or 'while' expected");
446 nextToken();
447 parseParens();
448 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();
490 }
491 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000492 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000493}
494
495void UnwrappedLineParser::parseCaseLabel() {
496 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
497 // FIXME: fix handling of complex expressions here.
498 do {
499 nextToken();
500 } while (!eof() && !FormatTok.Tok.is(tok::colon));
501 parseLabel();
502}
503
504void UnwrappedLineParser::parseSwitch() {
505 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
506 nextToken();
507 parseParens();
508 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000509 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000510 addUnwrappedLine();
511 } else {
512 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000513 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000514 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000515 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000516 }
517}
518
519void UnwrappedLineParser::parseAccessSpecifier() {
520 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000521 // Otherwise, we don't know what it is, and we'd better keep the next token.
522 if (FormatTok.Tok.is(tok::colon))
523 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000524 addUnwrappedLine();
525}
526
527void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000528 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000529 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000530 switch (FormatTok.Tok.getKind()) {
531 case tok::l_brace:
532 nextToken();
533 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000534 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000535 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000536 break;
537 case tok::l_paren:
538 parseParens();
539 break;
540 case tok::comma:
541 nextToken();
542 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000543 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000544 break;
545 case tok::r_brace:
546 if (HasContents)
547 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000548 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000549 nextToken();
550 break;
551 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000552 nextToken();
553 addUnwrappedLine();
554 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000555 default:
556 HasContents = true;
557 nextToken();
558 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000559 }
560 } while (!eof());
561}
562
Manuel Klimekde768542013-01-07 18:10:23 +0000563void UnwrappedLineParser::parseStructOrClass() {
564 nextToken();
565 do {
566 switch (FormatTok.Tok.getKind()) {
567 case tok::l_brace:
568 // FIXME: Think about how to resolve the error handling here.
569 parseBlock();
570 parseStructuralElement();
571 return;
572 case tok::semi:
573 nextToken();
574 addUnwrappedLine();
575 return;
576 default:
577 nextToken();
578 break;
579 }
580 } while (!eof());
581}
582
Nico Weber1abe6ea2013-01-09 21:15:03 +0000583void UnwrappedLineParser::parseObjCProtocolList() {
584 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
585 do
586 nextToken();
587 while (!eof() && FormatTok.Tok.isNot(tok::greater));
588 nextToken(); // Skip '>'.
589}
590
591void UnwrappedLineParser::parseObjCUntilAtEnd() {
592 do {
593 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
594 nextToken();
595 addUnwrappedLine();
596 break;
597 }
598 parseStructuralElement();
599 } while (!eof());
600}
601
Nico Weber50767d82013-01-09 23:25:37 +0000602void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000603 nextToken();
604 nextToken(); // interface name
605
606 // @interface can be followed by either a base class, or a category.
607 if (FormatTok.Tok.is(tok::colon)) {
608 nextToken();
609 nextToken(); // base class name
610 } else if (FormatTok.Tok.is(tok::l_paren))
611 // Skip category, if present.
612 parseParens();
613
Nico Weber1abe6ea2013-01-09 21:15:03 +0000614 if (FormatTok.Tok.is(tok::less))
615 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000616
617 // If instance variables are present, keep the '{' on the first line too.
618 if (FormatTok.Tok.is(tok::l_brace))
619 parseBlock();
620
621 // With instance variables, this puts '}' on its own line. Without instance
622 // variables, this ends the @interface line.
623 addUnwrappedLine();
624
Nico Weber1abe6ea2013-01-09 21:15:03 +0000625 parseObjCUntilAtEnd();
626}
Nico Weber27d13672013-01-09 20:25:35 +0000627
Nico Weber1abe6ea2013-01-09 21:15:03 +0000628void UnwrappedLineParser::parseObjCProtocol() {
629 nextToken();
630 nextToken(); // protocol name
631
632 if (FormatTok.Tok.is(tok::less))
633 parseObjCProtocolList();
634
635 // Check for protocol declaration.
636 if (FormatTok.Tok.is(tok::semi)) {
637 nextToken();
638 return addUnwrappedLine();
639 }
640
641 addUnwrappedLine();
642 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000643}
644
Daniel Jasperbac016b2012-12-03 18:12:45 +0000645void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000646 if (!RootTokenInitialized)
647 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000648 // Consume trailing comments.
649 while (!eof() && FormatTok.NewlinesBefore == 0 &&
650 FormatTok.Tok.is(tok::comment)) {
651 nextToken();
652 }
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000653#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
654 FormatToken* NextToken = &Line->RootToken;
655 llvm::errs() << "Line: ";
656 while (NextToken) {
657 llvm::errs() << NextToken->Tok.getName() << " ";
658 NextToken = NextToken->Children.empty() ? NULL : &NextToken->Children[0];
659 }
660 llvm::errs() << "\n";
661#endif
Manuel Klimek526ed112013-01-09 15:25:02 +0000662 Callback.consumeUnwrappedLine(*Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000663 RootTokenInitialized = false;
Manuel Klimek526ed112013-01-09 15:25:02 +0000664 LastInCurrentLine = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000665}
666
667bool UnwrappedLineParser::eof() const {
668 return FormatTok.Tok.is(tok::eof);
669}
670
671void UnwrappedLineParser::nextToken() {
672 if (eof())
673 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000674 if (RootTokenInitialized) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000675 assert(LastInCurrentLine->Children.empty());
Daniel Jasper26f7e782013-01-08 14:56:18 +0000676 LastInCurrentLine->Children.push_back(FormatTok);
677 LastInCurrentLine = &LastInCurrentLine->Children.back();
678 } else {
Manuel Klimek526ed112013-01-09 15:25:02 +0000679 Line->RootToken = FormatTok;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000680 RootTokenInitialized = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000681 LastInCurrentLine = &Line->RootToken;
682 }
683 if (MustBreakBeforeNextToken) {
684 LastInCurrentLine->MustBreakBefore = true;
685 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