blob: e9c6211313b5bf36926bc6f20863a4aebe856332 [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
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000170 if (!FormatTok.Tok.is(tok::r_brace)) {
171 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000172
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000173 Line->Level += AddLevels;
174 parseLevel(/*HasOpeningBrace=*/true);
175 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000176
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000177 if (!FormatTok.Tok.is(tok::r_brace))
178 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000179
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000180 }
Manuel Klimekde768542013-01-07 18:10:23 +0000181 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000182 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000183}
184
185void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000186 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000187 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000188 nextToken();
189
Manuel Klimeka080a182013-01-02 16:30:12 +0000190 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
191 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000192 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000193 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000194
Manuel Klimekd4397b92013-01-04 23:34:14 +0000195 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
196 case tok::pp_define:
197 parsePPDefine();
198 break;
199 default:
200 parsePPUnknown();
201 break;
202 }
203}
204
205void UnwrappedLineParser::parsePPDefine() {
206 nextToken();
207
208 if (FormatTok.Tok.getKind() != tok::identifier) {
209 parsePPUnknown();
210 return;
211 }
212 nextToken();
213 if (FormatTok.Tok.getKind() == tok::l_paren) {
214 parseParens();
215 }
216 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000217 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000218
219 // Errors during a preprocessor directive can only affect the layout of the
220 // preprocessor directive, and thus we ignore them. An alternative approach
221 // would be to use the same approach we use on the file level (no
222 // re-indentation if there was a structural error) within the macro
223 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000224 parseFile();
225}
226
227void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000228 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000229 nextToken();
230 } while (!eof());
231 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000232}
233
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000234void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000235 // Consume leading line comments, e.g. for branches without compounds.
236 while (FormatTok.Tok.is(tok::comment)) {
237 nextToken();
238 addUnwrappedLine();
239 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000240}
241
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000242void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000243 assert(!FormatTok.Tok.is(tok::l_brace));
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000244 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000245
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000246 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000247 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000248 case tok::at:
249 nextToken();
250 switch (FormatTok.Tok.getObjCKeywordID()) {
251 case tok::objc_public:
252 case tok::objc_protected:
253 case tok::objc_package:
254 case tok::objc_private:
255 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000256 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000257 case tok::objc_implementation:
258 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000259 case tok::objc_protocol:
260 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000261 case tok::objc_end:
262 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000263 case tok::objc_optional:
264 case tok::objc_required:
265 nextToken();
266 addUnwrappedLine();
267 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000268 default:
269 break;
270 }
271 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000272 case tok::kw_namespace:
273 parseNamespace();
274 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000275 case tok::kw_inline:
276 nextToken();
277 TokenNumber++;
278 if (FormatTok.Tok.is(tok::kw_namespace)) {
279 parseNamespace();
280 return;
281 }
282 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000283 case tok::kw_public:
284 case tok::kw_protected:
285 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000286 parseAccessSpecifier();
287 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000288 case tok::kw_if:
289 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000290 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000291 case tok::kw_for:
292 case tok::kw_while:
293 parseForOrWhileLoop();
294 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000295 case tok::kw_do:
296 parseDoWhile();
297 return;
298 case tok::kw_switch:
299 parseSwitch();
300 return;
301 case tok::kw_default:
302 nextToken();
303 parseLabel();
304 return;
305 case tok::kw_case:
306 parseCaseLabel();
307 return;
308 default:
309 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000310 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000311 do {
312 ++TokenNumber;
313 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000314 case tok::kw_enum:
315 parseEnum();
316 return;
Manuel Klimekde768542013-01-07 18:10:23 +0000317 case tok::kw_struct: // fallthrough
318 case tok::kw_class:
319 parseStructOrClass();
320 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000321 case tok::semi:
322 nextToken();
323 addUnwrappedLine();
324 return;
325 case tok::l_paren:
326 parseParens();
327 break;
328 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000329 // A block outside of parentheses must be the last part of a
330 // structural element.
331 // FIXME: Figure out cases where this is not true, and add projections for
332 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000333 parseBlock();
334 addUnwrappedLine();
335 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000336 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000337 nextToken();
338 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
339 parseLabel();
340 return;
341 }
342 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000343 case tok::equal:
344 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000345 if (FormatTok.Tok.is(tok::l_brace)) {
346 parseBracedList();
347 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000348 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000349 default:
350 nextToken();
351 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000352 }
353 } while (!eof());
354}
355
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000356void UnwrappedLineParser::parseBracedList() {
357 nextToken();
358
359 do {
360 switch (FormatTok.Tok.getKind()) {
361 case tok::l_brace:
362 parseBracedList();
363 break;
364 case tok::r_brace:
365 nextToken();
366 return;
367 default:
368 nextToken();
369 break;
370 }
371 } while (!eof());
372}
373
Daniel Jasperbac016b2012-12-03 18:12:45 +0000374void UnwrappedLineParser::parseParens() {
375 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
376 nextToken();
377 do {
378 switch (FormatTok.Tok.getKind()) {
379 case tok::l_paren:
380 parseParens();
381 break;
382 case tok::r_paren:
383 nextToken();
384 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000385 case tok::l_brace:
386 {
387 nextToken();
388 ScopedLineState LineState(*this);
389 Line->Level += 1;
390 parseLevel(/*HasOpeningBrace=*/true);
391 Line->Level -= 1;
392 }
393 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000394 default:
395 nextToken();
396 break;
397 }
398 } while (!eof());
399}
400
401void UnwrappedLineParser::parseIfThenElse() {
402 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
403 nextToken();
404 parseParens();
405 bool NeedsUnwrappedLine = false;
406 if (FormatTok.Tok.is(tok::l_brace)) {
407 parseBlock();
408 NeedsUnwrappedLine = true;
409 } else {
410 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000411 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000412 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000413 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000414 }
415 if (FormatTok.Tok.is(tok::kw_else)) {
416 nextToken();
417 if (FormatTok.Tok.is(tok::l_brace)) {
418 parseBlock();
419 addUnwrappedLine();
420 } else if (FormatTok.Tok.is(tok::kw_if)) {
421 parseIfThenElse();
422 } else {
423 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000424 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000425 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000426 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000427 }
428 } else if (NeedsUnwrappedLine) {
429 addUnwrappedLine();
430 }
431}
432
Alexander Kornienko15757312012-12-06 18:03:27 +0000433void UnwrappedLineParser::parseNamespace() {
434 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
435 nextToken();
436 if (FormatTok.Tok.is(tok::identifier))
437 nextToken();
438 if (FormatTok.Tok.is(tok::l_brace)) {
439 parseBlock(0);
440 addUnwrappedLine();
441 }
442 // FIXME: Add error handling.
443}
444
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000445void UnwrappedLineParser::parseForOrWhileLoop() {
446 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
447 "'for' or 'while' expected");
448 nextToken();
449 parseParens();
450 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();
509 parseParens();
510 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000511 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000512 addUnwrappedLine();
513 } else {
514 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000515 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000516 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000517 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000518 }
519}
520
521void UnwrappedLineParser::parseAccessSpecifier() {
522 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000523 // Otherwise, we don't know what it is, and we'd better keep the next token.
524 if (FormatTok.Tok.is(tok::colon))
525 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000526 addUnwrappedLine();
527}
528
529void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000530 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000531 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000532 switch (FormatTok.Tok.getKind()) {
533 case tok::l_brace:
534 nextToken();
535 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000536 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000537 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000538 break;
539 case tok::l_paren:
540 parseParens();
541 break;
542 case tok::comma:
543 nextToken();
544 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000545 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000546 break;
547 case tok::r_brace:
548 if (HasContents)
549 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000550 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000551 nextToken();
552 break;
553 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000554 nextToken();
555 addUnwrappedLine();
556 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000557 default:
558 HasContents = true;
559 nextToken();
560 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000561 }
562 } while (!eof());
563}
564
Manuel Klimekde768542013-01-07 18:10:23 +0000565void UnwrappedLineParser::parseStructOrClass() {
566 nextToken();
567 do {
568 switch (FormatTok.Tok.getKind()) {
569 case tok::l_brace:
570 // FIXME: Think about how to resolve the error handling here.
571 parseBlock();
572 parseStructuralElement();
573 return;
574 case tok::semi:
575 nextToken();
576 addUnwrappedLine();
577 return;
578 default:
579 nextToken();
580 break;
581 }
582 } while (!eof());
583}
584
Nico Weber1abe6ea2013-01-09 21:15:03 +0000585void UnwrappedLineParser::parseObjCProtocolList() {
586 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
587 do
588 nextToken();
589 while (!eof() && FormatTok.Tok.isNot(tok::greater));
590 nextToken(); // Skip '>'.
591}
592
593void UnwrappedLineParser::parseObjCUntilAtEnd() {
594 do {
595 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
596 nextToken();
597 addUnwrappedLine();
598 break;
599 }
600 parseStructuralElement();
601 } while (!eof());
602}
603
Nico Weber50767d82013-01-09 23:25:37 +0000604void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000605 nextToken();
606 nextToken(); // interface name
607
608 // @interface can be followed by either a base class, or a category.
609 if (FormatTok.Tok.is(tok::colon)) {
610 nextToken();
611 nextToken(); // base class name
612 } else if (FormatTok.Tok.is(tok::l_paren))
613 // Skip category, if present.
614 parseParens();
615
Nico Weber1abe6ea2013-01-09 21:15:03 +0000616 if (FormatTok.Tok.is(tok::less))
617 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000618
619 // If instance variables are present, keep the '{' on the first line too.
620 if (FormatTok.Tok.is(tok::l_brace))
621 parseBlock();
622
623 // With instance variables, this puts '}' on its own line. Without instance
624 // variables, this ends the @interface line.
625 addUnwrappedLine();
626
Nico Weber1abe6ea2013-01-09 21:15:03 +0000627 parseObjCUntilAtEnd();
628}
Nico Weber27d13672013-01-09 20:25:35 +0000629
Nico Weber1abe6ea2013-01-09 21:15:03 +0000630void UnwrappedLineParser::parseObjCProtocol() {
631 nextToken();
632 nextToken(); // protocol name
633
634 if (FormatTok.Tok.is(tok::less))
635 parseObjCProtocolList();
636
637 // Check for protocol declaration.
638 if (FormatTok.Tok.is(tok::semi)) {
639 nextToken();
640 return addUnwrappedLine();
641 }
642
643 addUnwrappedLine();
644 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000645}
646
Daniel Jasperbac016b2012-12-03 18:12:45 +0000647void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000648 if (!RootTokenInitialized)
649 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000650 // Consume trailing comments.
651 while (!eof() && FormatTok.NewlinesBefore == 0 &&
652 FormatTok.Tok.is(tok::comment)) {
653 nextToken();
654 }
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000655#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
656 FormatToken* NextToken = &Line->RootToken;
657 llvm::errs() << "Line: ";
658 while (NextToken) {
659 llvm::errs() << NextToken->Tok.getName() << " ";
660 NextToken = NextToken->Children.empty() ? NULL : &NextToken->Children[0];
661 }
662 llvm::errs() << "\n";
663#endif
Manuel Klimek526ed112013-01-09 15:25:02 +0000664 Callback.consumeUnwrappedLine(*Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000665 RootTokenInitialized = false;
Manuel Klimek526ed112013-01-09 15:25:02 +0000666 LastInCurrentLine = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000667}
668
669bool UnwrappedLineParser::eof() const {
670 return FormatTok.Tok.is(tok::eof);
671}
672
673void UnwrappedLineParser::nextToken() {
674 if (eof())
675 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000676 if (RootTokenInitialized) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000677 assert(LastInCurrentLine->Children.empty());
Daniel Jasper26f7e782013-01-08 14:56:18 +0000678 LastInCurrentLine->Children.push_back(FormatTok);
679 LastInCurrentLine = &LastInCurrentLine->Children.back();
680 } else {
Manuel Klimek526ed112013-01-09 15:25:02 +0000681 Line->RootToken = FormatTok;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000682 RootTokenInitialized = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000683 LastInCurrentLine = &Line->RootToken;
684 }
685 if (MustBreakBeforeNextToken) {
686 LastInCurrentLine->MustBreakBefore = true;
687 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000688 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000689 readToken();
690}
691
692void UnwrappedLineParser::readToken() {
693 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000694 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000695 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
696 FormatTok.IsFirst)) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000697 ScopedLineState BlockState(*this);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000698 parsePPDirective();
699 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000700}
701
Daniel Jaspercd162382013-01-07 13:26:07 +0000702} // end namespace format
703} // end namespace clang