blob: 0c8ff890491d996cf9f765abc0998fa5057d4734 [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;
Manuel Klimekde768542013-01-07 18:10:23 +0000320 case tok::kw_struct: // fallthrough
321 case tok::kw_class:
Manuel Klimek606e07e2013-01-11 18:13:04 +0000322 parseStructClassOrBracedList();
Manuel Klimekde768542013-01-07 18:10:23 +0000323 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000324 case tok::semi:
325 nextToken();
326 addUnwrappedLine();
327 return;
328 case tok::l_paren:
329 parseParens();
330 break;
331 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000332 // A block outside of parentheses must be the last part of a
333 // structural element.
334 // FIXME: Figure out cases where this is not true, and add projections for
335 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000336 parseBlock();
337 addUnwrappedLine();
338 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000339 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000340 nextToken();
341 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
342 parseLabel();
343 return;
344 }
345 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000346 case tok::equal:
347 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000348 if (FormatTok.Tok.is(tok::l_brace)) {
349 parseBracedList();
350 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000351 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000352 default:
353 nextToken();
354 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000355 }
356 } while (!eof());
357}
358
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000359void UnwrappedLineParser::parseBracedList() {
360 nextToken();
361
362 do {
363 switch (FormatTok.Tok.getKind()) {
364 case tok::l_brace:
365 parseBracedList();
366 break;
367 case tok::r_brace:
368 nextToken();
369 return;
370 default:
371 nextToken();
372 break;
373 }
374 } while (!eof());
375}
376
Daniel Jasperbac016b2012-12-03 18:12:45 +0000377void UnwrappedLineParser::parseParens() {
378 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
379 nextToken();
380 do {
381 switch (FormatTok.Tok.getKind()) {
382 case tok::l_paren:
383 parseParens();
384 break;
385 case tok::r_paren:
386 nextToken();
387 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000388 case tok::l_brace:
389 {
390 nextToken();
391 ScopedLineState LineState(*this);
392 Line->Level += 1;
393 parseLevel(/*HasOpeningBrace=*/true);
394 Line->Level -= 1;
395 }
396 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000397 default:
398 nextToken();
399 break;
400 }
401 } while (!eof());
402}
403
404void UnwrappedLineParser::parseIfThenElse() {
405 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
406 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000407 if (FormatTok.Tok.is(tok::l_paren))
408 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000409 bool NeedsUnwrappedLine = false;
410 if (FormatTok.Tok.is(tok::l_brace)) {
411 parseBlock();
412 NeedsUnwrappedLine = true;
413 } else {
414 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000415 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000416 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000417 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000418 }
419 if (FormatTok.Tok.is(tok::kw_else)) {
420 nextToken();
421 if (FormatTok.Tok.is(tok::l_brace)) {
422 parseBlock();
423 addUnwrappedLine();
424 } else if (FormatTok.Tok.is(tok::kw_if)) {
425 parseIfThenElse();
426 } else {
427 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000428 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000429 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000430 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000431 }
432 } else if (NeedsUnwrappedLine) {
433 addUnwrappedLine();
434 }
435}
436
Alexander Kornienko15757312012-12-06 18:03:27 +0000437void UnwrappedLineParser::parseNamespace() {
438 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
439 nextToken();
440 if (FormatTok.Tok.is(tok::identifier))
441 nextToken();
442 if (FormatTok.Tok.is(tok::l_brace)) {
443 parseBlock(0);
444 addUnwrappedLine();
445 }
446 // FIXME: Add error handling.
447}
448
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000449void UnwrappedLineParser::parseForOrWhileLoop() {
450 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
451 "'for' or 'while' expected");
452 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000453 if (FormatTok.Tok.is(tok::l_paren))
454 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000455 if (FormatTok.Tok.is(tok::l_brace)) {
456 parseBlock();
457 addUnwrappedLine();
458 } else {
459 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000460 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000461 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000462 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000463 }
464}
465
Daniel Jasperbac016b2012-12-03 18:12:45 +0000466void UnwrappedLineParser::parseDoWhile() {
467 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
468 nextToken();
469 if (FormatTok.Tok.is(tok::l_brace)) {
470 parseBlock();
471 } else {
472 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000473 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000474 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000475 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000476 }
477
Alexander Kornienko393b0082012-12-04 15:40:36 +0000478 // FIXME: Add error handling.
479 if (!FormatTok.Tok.is(tok::kw_while)) {
480 addUnwrappedLine();
481 return;
482 }
483
Daniel Jasperbac016b2012-12-03 18:12:45 +0000484 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000485 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000486}
487
488void UnwrappedLineParser::parseLabel() {
489 // FIXME: remove all asserts.
490 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
491 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000492 unsigned OldLineLevel = Line->Level;
493 if (Line->Level > 0)
494 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000495 if (FormatTok.Tok.is(tok::l_brace)) {
496 parseBlock();
497 }
498 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000499 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000500}
501
502void UnwrappedLineParser::parseCaseLabel() {
503 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
504 // FIXME: fix handling of complex expressions here.
505 do {
506 nextToken();
507 } while (!eof() && !FormatTok.Tok.is(tok::colon));
508 parseLabel();
509}
510
511void UnwrappedLineParser::parseSwitch() {
512 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
513 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000514 if (FormatTok.Tok.is(tok::l_paren))
515 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000516 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000517 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000518 addUnwrappedLine();
519 } else {
520 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000521 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000522 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000523 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000524 }
525}
526
527void UnwrappedLineParser::parseAccessSpecifier() {
528 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000529 // Otherwise, we don't know what it is, and we'd better keep the next token.
530 if (FormatTok.Tok.is(tok::colon))
531 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000532 addUnwrappedLine();
533}
534
535void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000536 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000537 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000538 switch (FormatTok.Tok.getKind()) {
539 case tok::l_brace:
540 nextToken();
541 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000542 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000543 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000544 break;
545 case tok::l_paren:
546 parseParens();
547 break;
548 case tok::comma:
549 nextToken();
550 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000551 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000552 break;
553 case tok::r_brace:
554 if (HasContents)
555 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000556 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000557 nextToken();
558 break;
559 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000560 nextToken();
561 addUnwrappedLine();
562 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000563 default:
564 HasContents = true;
565 nextToken();
566 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000567 }
568 } while (!eof());
569}
570
Manuel Klimek606e07e2013-01-11 18:13:04 +0000571void UnwrappedLineParser::parseStructClassOrBracedList() {
Manuel Klimekde768542013-01-07 18:10:23 +0000572 nextToken();
573 do {
574 switch (FormatTok.Tok.getKind()) {
575 case tok::l_brace:
576 // FIXME: Think about how to resolve the error handling here.
577 parseBlock();
578 parseStructuralElement();
579 return;
580 case tok::semi:
581 nextToken();
582 addUnwrappedLine();
583 return;
Manuel Klimek606e07e2013-01-11 18:13:04 +0000584 case tok::equal:
585 nextToken();
586 if (FormatTok.Tok.is(tok::l_brace)) {
587 parseBracedList();
588 }
589 break;
Manuel Klimekde768542013-01-07 18:10:23 +0000590 default:
591 nextToken();
592 break;
593 }
594 } while (!eof());
595}
596
Nico Weber1abe6ea2013-01-09 21:15:03 +0000597void UnwrappedLineParser::parseObjCProtocolList() {
598 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
599 do
600 nextToken();
601 while (!eof() && FormatTok.Tok.isNot(tok::greater));
602 nextToken(); // Skip '>'.
603}
604
605void UnwrappedLineParser::parseObjCUntilAtEnd() {
606 do {
607 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
608 nextToken();
609 addUnwrappedLine();
610 break;
611 }
612 parseStructuralElement();
613 } while (!eof());
614}
615
Nico Weber50767d82013-01-09 23:25:37 +0000616void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000617 nextToken();
618 nextToken(); // interface name
619
620 // @interface can be followed by either a base class, or a category.
621 if (FormatTok.Tok.is(tok::colon)) {
622 nextToken();
623 nextToken(); // base class name
624 } else if (FormatTok.Tok.is(tok::l_paren))
625 // Skip category, if present.
626 parseParens();
627
Nico Weber1abe6ea2013-01-09 21:15:03 +0000628 if (FormatTok.Tok.is(tok::less))
629 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000630
631 // If instance variables are present, keep the '{' on the first line too.
632 if (FormatTok.Tok.is(tok::l_brace))
633 parseBlock();
634
635 // With instance variables, this puts '}' on its own line. Without instance
636 // variables, this ends the @interface line.
637 addUnwrappedLine();
638
Nico Weber1abe6ea2013-01-09 21:15:03 +0000639 parseObjCUntilAtEnd();
640}
Nico Weber27d13672013-01-09 20:25:35 +0000641
Nico Weber1abe6ea2013-01-09 21:15:03 +0000642void UnwrappedLineParser::parseObjCProtocol() {
643 nextToken();
644 nextToken(); // protocol name
645
646 if (FormatTok.Tok.is(tok::less))
647 parseObjCProtocolList();
648
649 // Check for protocol declaration.
650 if (FormatTok.Tok.is(tok::semi)) {
651 nextToken();
652 return addUnwrappedLine();
653 }
654
655 addUnwrappedLine();
656 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000657}
658
Daniel Jasperbac016b2012-12-03 18:12:45 +0000659void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000660 if (!RootTokenInitialized)
661 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000662 // Consume trailing comments.
663 while (!eof() && FormatTok.NewlinesBefore == 0 &&
664 FormatTok.Tok.is(tok::comment)) {
665 nextToken();
666 }
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000667#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
668 FormatToken* NextToken = &Line->RootToken;
669 llvm::errs() << "Line: ";
670 while (NextToken) {
671 llvm::errs() << NextToken->Tok.getName() << " ";
672 NextToken = NextToken->Children.empty() ? NULL : &NextToken->Children[0];
673 }
674 llvm::errs() << "\n";
675#endif
Manuel Klimek526ed112013-01-09 15:25:02 +0000676 Callback.consumeUnwrappedLine(*Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000677 RootTokenInitialized = false;
Manuel Klimek526ed112013-01-09 15:25:02 +0000678 LastInCurrentLine = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000679}
680
681bool UnwrappedLineParser::eof() const {
682 return FormatTok.Tok.is(tok::eof);
683}
684
685void UnwrappedLineParser::nextToken() {
686 if (eof())
687 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000688 if (RootTokenInitialized) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000689 assert(LastInCurrentLine->Children.empty());
Daniel Jasper26f7e782013-01-08 14:56:18 +0000690 LastInCurrentLine->Children.push_back(FormatTok);
691 LastInCurrentLine = &LastInCurrentLine->Children.back();
692 } else {
Manuel Klimek526ed112013-01-09 15:25:02 +0000693 Line->RootToken = FormatTok;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000694 RootTokenInitialized = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000695 LastInCurrentLine = &Line->RootToken;
696 }
697 if (MustBreakBeforeNextToken) {
698 LastInCurrentLine->MustBreakBefore = true;
699 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000700 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000701 readToken();
702}
703
704void UnwrappedLineParser::readToken() {
705 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000706 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000707 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
708 FormatTok.IsFirst)) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000709 ScopedLineState BlockState(*this);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000710 parsePPDirective();
711 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000712}
713
Daniel Jaspercd162382013-01-07 13:26:07 +0000714} // end namespace format
715} // end namespace clang