blob: b3671b30409204b5c88e54f2a6c38531954ca06f [file] [log] [blame]
Daniel Jasperbac016b2012-12-03 18:12:45 +00001//===--- UnwrappedLineParser.cpp - Format C++ code ------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file contains the implementation of the UnwrappedLineParser,
12/// which turns a stream of tokens into UnwrappedLines.
13///
14/// This is EXPERIMENTAL code under heavy development. It is not in a state yet,
15/// where it can be used to format real code.
16///
17//===----------------------------------------------------------------------===//
18
19#include "UnwrappedLineParser.h"
Alexander Kornienko3048aea2013-01-10 15:05:09 +000020#include "clang/Basic/Diagnostic.h"
Daniel Jasperbac016b2012-12-03 18:12:45 +000021#include "llvm/Support/raw_ostream.h"
22
Manuel Klimek4c60fc62013-01-10 10:05:08 +000023// Uncomment to get debug output from the UnwrappedLineParser.
24// Use in combination with --gtest_filter=*TestName* to limit the output to a
25// single test.
26// #define UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
27
Daniel Jasperbac016b2012-12-03 18:12:45 +000028namespace clang {
29namespace format {
30
Manuel Klimekd4397b92013-01-04 23:34:14 +000031class ScopedMacroState : public FormatTokenSource {
32public:
33 ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
34 FormatToken &ResetToken)
35 : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
Manuel Klimekc37b4d62013-01-05 22:14:16 +000036 PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource) {
Manuel Klimekd4397b92013-01-04 23:34:14 +000037 TokenSource = this;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000038 Line.Level = 0;
Manuel Klimekd4397b92013-01-04 23:34:14 +000039 Line.InPPDirective = true;
40 }
41
42 ~ScopedMacroState() {
43 TokenSource = PreviousTokenSource;
44 ResetToken = Token;
45 Line.InPPDirective = false;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000046 Line.Level = PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000047 }
48
49 virtual FormatToken getNextToken() {
Manuel Klimekdd5b1012013-01-07 10:03:37 +000050 // The \c UnwrappedLineParser guards against this by never calling
51 // \c getNextToken() after it has encountered the first eof token.
52 assert(!eof());
Manuel Klimekd4397b92013-01-04 23:34:14 +000053 Token = PreviousTokenSource->getNextToken();
54 if (eof())
55 return createEOF();
56 return Token;
57 }
58
59private:
60 bool eof() {
61 return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline;
62 }
63
64 FormatToken createEOF() {
65 FormatToken FormatTok;
66 FormatTok.Tok.startToken();
67 FormatTok.Tok.setKind(tok::eof);
68 return FormatTok;
69 }
70
71 UnwrappedLine &Line;
72 FormatTokenSource *&TokenSource;
73 FormatToken &ResetToken;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000074 unsigned PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000075 FormatTokenSource *PreviousTokenSource;
76
77 FormatToken Token;
78};
79
Manuel Klimekbb42bf12013-01-10 11:52:21 +000080class ScopedLineState {
81public:
82 ScopedLineState(UnwrappedLineParser &Parser) : Parser(Parser) {
83 PreBlockLine = Parser.Line.take();
84 Parser.Line.reset(new UnwrappedLine(*PreBlockLine));
85 assert(Parser.LastInCurrentLine == NULL ||
86 Parser.LastInCurrentLine->Children.empty());
87 PreBlockLastToken = Parser.LastInCurrentLine;
88 PreBlockRootTokenInitialized = Parser.RootTokenInitialized;
89 Parser.RootTokenInitialized = false;
90 Parser.LastInCurrentLine = NULL;
91 }
92
93 ~ScopedLineState() {
94 if (Parser.RootTokenInitialized) {
95 Parser.addUnwrappedLine();
96 }
97 assert(!Parser.RootTokenInitialized);
98 Parser.Line.reset(PreBlockLine);
99 Parser.RootTokenInitialized = PreBlockRootTokenInitialized;
100 Parser.LastInCurrentLine = PreBlockLastToken;
101 assert(Parser.LastInCurrentLine == NULL ||
102 Parser.LastInCurrentLine->Children.empty());
103 Parser.MustBreakBeforeNextToken = true;
104 }
105
106private:
107 UnwrappedLineParser &Parser;
108
109 UnwrappedLine *PreBlockLine;
110 FormatToken* PreBlockLastToken;
111 bool PreBlockRootTokenInitialized;
112};
113
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000114UnwrappedLineParser::UnwrappedLineParser(
115 clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
116 FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback)
Manuel Klimek526ed112013-01-09 15:25:02 +0000117 : Line(new UnwrappedLine), RootTokenInitialized(false),
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000118 LastInCurrentLine(NULL), MustBreakBeforeNextToken(false), Diag(Diag),
119 Style(Style), Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000120}
121
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000122bool UnwrappedLineParser::parse() {
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000123#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
124 llvm::errs() << "----\n";
125#endif
Manuel Klimekd4397b92013-01-04 23:34:14 +0000126 readToken();
127 return parseFile();
128}
129
130bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +0000131 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000132 // Make sure to format the remaining tokens.
133 addUnwrappedLine();
134 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000135}
136
Manuel Klimeka5342db2013-01-06 20:07:31 +0000137bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000138 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000139 do {
140 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000141 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000142 nextToken();
143 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000144 break;
145 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000146 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000147 addUnwrappedLine();
148 break;
149 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000150 if (HasOpeningBrace) {
151 return false;
152 } else {
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000153 Diag.Report(FormatTok.Tok.getLocation(),
154 Diag.getCustomDiagID(clang::DiagnosticsEngine::Error,
Alexander Kornienko276a2092013-01-11 16:03:45 +0000155 "unexpected '}'"));
Manuel Klimeka5342db2013-01-06 20:07:31 +0000156 Error = true;
157 nextToken();
158 addUnwrappedLine();
159 }
160 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000161 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000162 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000163 break;
164 }
165 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000166 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000167}
168
Alexander Kornienko15757312012-12-06 18:03:27 +0000169bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000170 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000171 nextToken();
172
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000173 if (!FormatTok.Tok.is(tok::r_brace)) {
174 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000175
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000176 Line->Level += AddLevels;
177 parseLevel(/*HasOpeningBrace=*/true);
178 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000179
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000180 if (!FormatTok.Tok.is(tok::r_brace))
181 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000182
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000183 }
Manuel Klimekde768542013-01-07 18:10:23 +0000184 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000185 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000186}
187
188void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000189 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000190 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000191 nextToken();
192
Manuel Klimeka080a182013-01-02 16:30:12 +0000193 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
194 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000195 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000196 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000197
Manuel Klimekd4397b92013-01-04 23:34:14 +0000198 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
199 case tok::pp_define:
200 parsePPDefine();
201 break;
202 default:
203 parsePPUnknown();
204 break;
205 }
206}
207
208void UnwrappedLineParser::parsePPDefine() {
209 nextToken();
210
211 if (FormatTok.Tok.getKind() != tok::identifier) {
212 parsePPUnknown();
213 return;
214 }
215 nextToken();
216 if (FormatTok.Tok.getKind() == tok::l_paren) {
217 parseParens();
218 }
219 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000220 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000221
222 // Errors during a preprocessor directive can only affect the layout of the
223 // preprocessor directive, and thus we ignore them. An alternative approach
224 // would be to use the same approach we use on the file level (no
225 // re-indentation if there was a structural error) within the macro
226 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000227 parseFile();
228}
229
230void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000231 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000232 nextToken();
233 } while (!eof());
234 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000235}
236
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000237void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000238 // Consume leading line comments, e.g. for branches without compounds.
239 while (FormatTok.Tok.is(tok::comment)) {
240 nextToken();
241 addUnwrappedLine();
242 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000243}
244
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000245void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000246 assert(!FormatTok.Tok.is(tok::l_brace));
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000247 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000248
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000249 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000250 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000251 case tok::at:
252 nextToken();
253 switch (FormatTok.Tok.getObjCKeywordID()) {
254 case tok::objc_public:
255 case tok::objc_protected:
256 case tok::objc_package:
257 case tok::objc_private:
258 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000259 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000260 case tok::objc_implementation:
261 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000262 case tok::objc_protocol:
263 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000264 case tok::objc_end:
265 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000266 case tok::objc_optional:
267 case tok::objc_required:
268 nextToken();
269 addUnwrappedLine();
270 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000271 default:
272 break;
273 }
274 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000275 case tok::kw_namespace:
276 parseNamespace();
277 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000278 case tok::kw_inline:
279 nextToken();
280 TokenNumber++;
281 if (FormatTok.Tok.is(tok::kw_namespace)) {
282 parseNamespace();
283 return;
284 }
285 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000286 case tok::kw_public:
287 case tok::kw_protected:
288 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000289 parseAccessSpecifier();
290 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000291 case tok::kw_if:
292 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000293 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000294 case tok::kw_for:
295 case tok::kw_while:
296 parseForOrWhileLoop();
297 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000298 case tok::kw_do:
299 parseDoWhile();
300 return;
301 case tok::kw_switch:
302 parseSwitch();
303 return;
304 case tok::kw_default:
305 nextToken();
306 parseLabel();
307 return;
308 case tok::kw_case:
309 parseCaseLabel();
310 return;
311 default:
312 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000313 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000314 do {
315 ++TokenNumber;
316 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000317 case tok::kw_enum:
318 parseEnum();
319 return;
Daniel Jasper17746032013-01-13 14:39:04 +0000320 case tok::kw_struct: // fallthrough
321 case tok::kw_union: // fallthrough
Manuel Klimekde768542013-01-07 18:10:23 +0000322 case tok::kw_class:
Manuel Klimek606e07e2013-01-11 18:13:04 +0000323 parseStructClassOrBracedList();
Manuel Klimekde768542013-01-07 18:10:23 +0000324 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000325 case tok::semi:
326 nextToken();
327 addUnwrappedLine();
328 return;
329 case tok::l_paren:
330 parseParens();
331 break;
332 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000333 // A block outside of parentheses must be the last part of a
334 // structural element.
335 // FIXME: Figure out cases where this is not true, and add projections for
336 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000337 parseBlock();
338 addUnwrappedLine();
339 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000340 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000341 nextToken();
342 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
343 parseLabel();
344 return;
345 }
346 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000347 case tok::equal:
348 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000349 if (FormatTok.Tok.is(tok::l_brace)) {
350 parseBracedList();
351 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000352 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000353 default:
354 nextToken();
355 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000356 }
357 } while (!eof());
358}
359
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000360void UnwrappedLineParser::parseBracedList() {
361 nextToken();
362
363 do {
364 switch (FormatTok.Tok.getKind()) {
365 case tok::l_brace:
366 parseBracedList();
367 break;
368 case tok::r_brace:
369 nextToken();
370 return;
371 default:
372 nextToken();
373 break;
374 }
375 } while (!eof());
376}
377
Daniel Jasperbac016b2012-12-03 18:12:45 +0000378void UnwrappedLineParser::parseParens() {
379 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
380 nextToken();
381 do {
382 switch (FormatTok.Tok.getKind()) {
383 case tok::l_paren:
384 parseParens();
385 break;
386 case tok::r_paren:
387 nextToken();
388 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000389 case tok::l_brace:
390 {
391 nextToken();
392 ScopedLineState LineState(*this);
393 Line->Level += 1;
394 parseLevel(/*HasOpeningBrace=*/true);
395 Line->Level -= 1;
396 }
397 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000398 default:
399 nextToken();
400 break;
401 }
402 } while (!eof());
403}
404
405void UnwrappedLineParser::parseIfThenElse() {
406 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
407 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000408 if (FormatTok.Tok.is(tok::l_paren))
409 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000410 bool NeedsUnwrappedLine = false;
411 if (FormatTok.Tok.is(tok::l_brace)) {
412 parseBlock();
413 NeedsUnwrappedLine = true;
414 } else {
415 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000416 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000417 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000418 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000419 }
420 if (FormatTok.Tok.is(tok::kw_else)) {
421 nextToken();
422 if (FormatTok.Tok.is(tok::l_brace)) {
423 parseBlock();
424 addUnwrappedLine();
425 } else if (FormatTok.Tok.is(tok::kw_if)) {
426 parseIfThenElse();
427 } else {
428 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000429 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000430 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000431 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000432 }
433 } else if (NeedsUnwrappedLine) {
434 addUnwrappedLine();
435 }
436}
437
Alexander Kornienko15757312012-12-06 18:03:27 +0000438void UnwrappedLineParser::parseNamespace() {
439 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
440 nextToken();
441 if (FormatTok.Tok.is(tok::identifier))
442 nextToken();
443 if (FormatTok.Tok.is(tok::l_brace)) {
444 parseBlock(0);
445 addUnwrappedLine();
446 }
447 // FIXME: Add error handling.
448}
449
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000450void UnwrappedLineParser::parseForOrWhileLoop() {
451 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
452 "'for' or 'while' expected");
453 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000454 if (FormatTok.Tok.is(tok::l_paren))
455 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000456 if (FormatTok.Tok.is(tok::l_brace)) {
457 parseBlock();
458 addUnwrappedLine();
459 } else {
460 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000461 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000462 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000463 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000464 }
465}
466
Daniel Jasperbac016b2012-12-03 18:12:45 +0000467void UnwrappedLineParser::parseDoWhile() {
468 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
469 nextToken();
470 if (FormatTok.Tok.is(tok::l_brace)) {
471 parseBlock();
472 } else {
473 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000474 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000475 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000476 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000477 }
478
Alexander Kornienko393b0082012-12-04 15:40:36 +0000479 // FIXME: Add error handling.
480 if (!FormatTok.Tok.is(tok::kw_while)) {
481 addUnwrappedLine();
482 return;
483 }
484
Daniel Jasperbac016b2012-12-03 18:12:45 +0000485 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000486 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000487}
488
489void UnwrappedLineParser::parseLabel() {
490 // FIXME: remove all asserts.
491 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
492 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000493 unsigned OldLineLevel = Line->Level;
494 if (Line->Level > 0)
495 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000496 if (FormatTok.Tok.is(tok::l_brace)) {
497 parseBlock();
498 }
499 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000500 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000501}
502
503void UnwrappedLineParser::parseCaseLabel() {
504 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
505 // FIXME: fix handling of complex expressions here.
506 do {
507 nextToken();
508 } while (!eof() && !FormatTok.Tok.is(tok::colon));
509 parseLabel();
510}
511
512void UnwrappedLineParser::parseSwitch() {
513 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
514 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000515 if (FormatTok.Tok.is(tok::l_paren))
516 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000517 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000518 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000519 addUnwrappedLine();
520 } else {
521 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000522 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000523 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000524 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000525 }
526}
527
528void UnwrappedLineParser::parseAccessSpecifier() {
529 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000530 // Otherwise, we don't know what it is, and we'd better keep the next token.
531 if (FormatTok.Tok.is(tok::colon))
532 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000533 addUnwrappedLine();
534}
535
536void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000537 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000538 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000539 switch (FormatTok.Tok.getKind()) {
540 case tok::l_brace:
541 nextToken();
542 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000543 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000544 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000545 break;
546 case tok::l_paren:
547 parseParens();
548 break;
549 case tok::comma:
550 nextToken();
551 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000552 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000553 break;
554 case tok::r_brace:
555 if (HasContents)
556 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000557 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000558 nextToken();
559 break;
560 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000561 nextToken();
562 addUnwrappedLine();
563 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000564 default:
565 HasContents = true;
566 nextToken();
567 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000568 }
569 } while (!eof());
570}
571
Manuel Klimek606e07e2013-01-11 18:13:04 +0000572void UnwrappedLineParser::parseStructClassOrBracedList() {
Manuel Klimekde768542013-01-07 18:10:23 +0000573 nextToken();
574 do {
575 switch (FormatTok.Tok.getKind()) {
576 case tok::l_brace:
577 // FIXME: Think about how to resolve the error handling here.
578 parseBlock();
579 parseStructuralElement();
580 return;
581 case tok::semi:
582 nextToken();
583 addUnwrappedLine();
584 return;
Manuel Klimek606e07e2013-01-11 18:13:04 +0000585 case tok::equal:
586 nextToken();
587 if (FormatTok.Tok.is(tok::l_brace)) {
588 parseBracedList();
589 }
590 break;
Manuel Klimekde768542013-01-07 18:10:23 +0000591 default:
592 nextToken();
593 break;
594 }
595 } while (!eof());
596}
597
Nico Weber1abe6ea2013-01-09 21:15:03 +0000598void UnwrappedLineParser::parseObjCProtocolList() {
599 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
600 do
601 nextToken();
602 while (!eof() && FormatTok.Tok.isNot(tok::greater));
603 nextToken(); // Skip '>'.
604}
605
606void UnwrappedLineParser::parseObjCUntilAtEnd() {
607 do {
608 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
609 nextToken();
610 addUnwrappedLine();
611 break;
612 }
613 parseStructuralElement();
614 } while (!eof());
615}
616
Nico Weber50767d82013-01-09 23:25:37 +0000617void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000618 nextToken();
619 nextToken(); // interface name
620
621 // @interface can be followed by either a base class, or a category.
622 if (FormatTok.Tok.is(tok::colon)) {
623 nextToken();
624 nextToken(); // base class name
625 } else if (FormatTok.Tok.is(tok::l_paren))
626 // Skip category, if present.
627 parseParens();
628
Nico Weber1abe6ea2013-01-09 21:15:03 +0000629 if (FormatTok.Tok.is(tok::less))
630 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000631
632 // If instance variables are present, keep the '{' on the first line too.
633 if (FormatTok.Tok.is(tok::l_brace))
634 parseBlock();
635
636 // With instance variables, this puts '}' on its own line. Without instance
637 // variables, this ends the @interface line.
638 addUnwrappedLine();
639
Nico Weber1abe6ea2013-01-09 21:15:03 +0000640 parseObjCUntilAtEnd();
641}
Nico Weber27d13672013-01-09 20:25:35 +0000642
Nico Weber1abe6ea2013-01-09 21:15:03 +0000643void UnwrappedLineParser::parseObjCProtocol() {
644 nextToken();
645 nextToken(); // protocol name
646
647 if (FormatTok.Tok.is(tok::less))
648 parseObjCProtocolList();
649
650 // Check for protocol declaration.
651 if (FormatTok.Tok.is(tok::semi)) {
652 nextToken();
653 return addUnwrappedLine();
654 }
655
656 addUnwrappedLine();
657 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000658}
659
Daniel Jasperbac016b2012-12-03 18:12:45 +0000660void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000661 if (!RootTokenInitialized)
662 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000663 // Consume trailing comments.
664 while (!eof() && FormatTok.NewlinesBefore == 0 &&
665 FormatTok.Tok.is(tok::comment)) {
666 nextToken();
667 }
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000668#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
669 FormatToken* NextToken = &Line->RootToken;
670 llvm::errs() << "Line: ";
671 while (NextToken) {
672 llvm::errs() << NextToken->Tok.getName() << " ";
673 NextToken = NextToken->Children.empty() ? NULL : &NextToken->Children[0];
674 }
675 llvm::errs() << "\n";
676#endif
Manuel Klimek526ed112013-01-09 15:25:02 +0000677 Callback.consumeUnwrappedLine(*Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000678 RootTokenInitialized = false;
Manuel Klimek526ed112013-01-09 15:25:02 +0000679 LastInCurrentLine = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000680}
681
682bool UnwrappedLineParser::eof() const {
683 return FormatTok.Tok.is(tok::eof);
684}
685
686void UnwrappedLineParser::nextToken() {
687 if (eof())
688 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000689 if (RootTokenInitialized) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000690 assert(LastInCurrentLine->Children.empty());
Daniel Jasper26f7e782013-01-08 14:56:18 +0000691 LastInCurrentLine->Children.push_back(FormatTok);
692 LastInCurrentLine = &LastInCurrentLine->Children.back();
693 } else {
Manuel Klimek526ed112013-01-09 15:25:02 +0000694 Line->RootToken = FormatTok;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000695 RootTokenInitialized = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000696 LastInCurrentLine = &Line->RootToken;
697 }
698 if (MustBreakBeforeNextToken) {
699 LastInCurrentLine->MustBreakBefore = true;
700 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000701 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000702 readToken();
703}
704
705void UnwrappedLineParser::readToken() {
706 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000707 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000708 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
709 FormatTok.IsFirst)) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000710 ScopedLineState BlockState(*this);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000711 parsePPDirective();
712 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000713}
714
Daniel Jaspercd162382013-01-07 13:26:07 +0000715} // end namespace format
716} // end namespace clang