blob: fe522ac9d8f8d8f41754c8a3980f6f1fbdc3ab5b [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 Klimek47ea7f62013-01-15 13:38:33 +0000323 parseRecord();
324 // A record declaration or definition is always the start of a structural
325 // element.
326 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000327 case tok::semi:
328 nextToken();
329 addUnwrappedLine();
330 return;
331 case tok::l_paren:
332 parseParens();
333 break;
334 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000335 // A block outside of parentheses must be the last part of a
336 // structural element.
337 // FIXME: Figure out cases where this is not true, and add projections for
338 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000339 parseBlock();
340 addUnwrappedLine();
341 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000342 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000343 nextToken();
344 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
345 parseLabel();
346 return;
347 }
348 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000349 case tok::equal:
350 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000351 if (FormatTok.Tok.is(tok::l_brace)) {
352 parseBracedList();
353 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000354 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000355 default:
356 nextToken();
357 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000358 }
359 } while (!eof());
360}
361
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000362void UnwrappedLineParser::parseBracedList() {
363 nextToken();
364
365 do {
366 switch (FormatTok.Tok.getKind()) {
367 case tok::l_brace:
368 parseBracedList();
369 break;
370 case tok::r_brace:
371 nextToken();
372 return;
373 default:
374 nextToken();
375 break;
376 }
377 } while (!eof());
378}
379
Daniel Jasperbac016b2012-12-03 18:12:45 +0000380void UnwrappedLineParser::parseParens() {
381 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
382 nextToken();
383 do {
384 switch (FormatTok.Tok.getKind()) {
385 case tok::l_paren:
386 parseParens();
387 break;
388 case tok::r_paren:
389 nextToken();
390 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000391 case tok::l_brace:
392 {
393 nextToken();
394 ScopedLineState LineState(*this);
395 Line->Level += 1;
396 parseLevel(/*HasOpeningBrace=*/true);
397 Line->Level -= 1;
398 }
399 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000400 default:
401 nextToken();
402 break;
403 }
404 } while (!eof());
405}
406
407void UnwrappedLineParser::parseIfThenElse() {
408 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
409 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000410 if (FormatTok.Tok.is(tok::l_paren))
411 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000412 bool NeedsUnwrappedLine = false;
413 if (FormatTok.Tok.is(tok::l_brace)) {
414 parseBlock();
415 NeedsUnwrappedLine = true;
416 } else {
417 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000418 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000419 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000420 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000421 }
422 if (FormatTok.Tok.is(tok::kw_else)) {
423 nextToken();
424 if (FormatTok.Tok.is(tok::l_brace)) {
425 parseBlock();
426 addUnwrappedLine();
427 } else if (FormatTok.Tok.is(tok::kw_if)) {
428 parseIfThenElse();
429 } else {
430 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000431 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000432 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000433 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000434 }
435 } else if (NeedsUnwrappedLine) {
436 addUnwrappedLine();
437 }
438}
439
Alexander Kornienko15757312012-12-06 18:03:27 +0000440void UnwrappedLineParser::parseNamespace() {
441 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
442 nextToken();
443 if (FormatTok.Tok.is(tok::identifier))
444 nextToken();
445 if (FormatTok.Tok.is(tok::l_brace)) {
446 parseBlock(0);
447 addUnwrappedLine();
448 }
449 // FIXME: Add error handling.
450}
451
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000452void UnwrappedLineParser::parseForOrWhileLoop() {
453 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
454 "'for' or 'while' expected");
455 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000456 if (FormatTok.Tok.is(tok::l_paren))
457 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000458 if (FormatTok.Tok.is(tok::l_brace)) {
459 parseBlock();
460 addUnwrappedLine();
461 } else {
462 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000463 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000464 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000465 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000466 }
467}
468
Daniel Jasperbac016b2012-12-03 18:12:45 +0000469void UnwrappedLineParser::parseDoWhile() {
470 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
471 nextToken();
472 if (FormatTok.Tok.is(tok::l_brace)) {
473 parseBlock();
474 } else {
475 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000476 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000477 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000478 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000479 }
480
Alexander Kornienko393b0082012-12-04 15:40:36 +0000481 // FIXME: Add error handling.
482 if (!FormatTok.Tok.is(tok::kw_while)) {
483 addUnwrappedLine();
484 return;
485 }
486
Daniel Jasperbac016b2012-12-03 18:12:45 +0000487 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000488 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000489}
490
491void UnwrappedLineParser::parseLabel() {
492 // FIXME: remove all asserts.
493 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
494 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000495 unsigned OldLineLevel = Line->Level;
496 if (Line->Level > 0)
497 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000498 if (FormatTok.Tok.is(tok::l_brace)) {
499 parseBlock();
500 }
501 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000502 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000503}
504
505void UnwrappedLineParser::parseCaseLabel() {
506 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
507 // FIXME: fix handling of complex expressions here.
508 do {
509 nextToken();
510 } while (!eof() && !FormatTok.Tok.is(tok::colon));
511 parseLabel();
512}
513
514void UnwrappedLineParser::parseSwitch() {
515 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
516 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000517 if (FormatTok.Tok.is(tok::l_paren))
518 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000519 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000520 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000521 addUnwrappedLine();
522 } else {
523 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000524 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000525 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000526 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000527 }
528}
529
530void UnwrappedLineParser::parseAccessSpecifier() {
531 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000532 // Otherwise, we don't know what it is, and we'd better keep the next token.
533 if (FormatTok.Tok.is(tok::colon))
534 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000535 addUnwrappedLine();
536}
537
538void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000539 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000540 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000541 switch (FormatTok.Tok.getKind()) {
542 case tok::l_brace:
543 nextToken();
544 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000545 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000546 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000547 break;
548 case tok::l_paren:
549 parseParens();
550 break;
551 case tok::comma:
552 nextToken();
553 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000554 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000555 break;
556 case tok::r_brace:
557 if (HasContents)
558 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000559 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000560 nextToken();
561 break;
562 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000563 nextToken();
564 addUnwrappedLine();
565 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000566 default:
567 HasContents = true;
568 nextToken();
569 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000570 }
571 } while (!eof());
572}
573
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000574void UnwrappedLineParser::parseRecord() {
Manuel Klimekde768542013-01-07 18:10:23 +0000575 nextToken();
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000576 if (FormatTok.Tok.is(tok::identifier) ||
577 FormatTok.Tok.is(tok::kw___attribute) ||
578 FormatTok.Tok.is(tok::kw___declspec)) {
579 nextToken();
580 // We can have macros or attributes in between 'class' and the class name.
581 if (FormatTok.Tok.is(tok::l_paren)) {
582 parseParens();
Manuel Klimekde768542013-01-07 18:10:23 +0000583 }
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000584 if (FormatTok.Tok.is(tok::identifier))
585 nextToken();
586
587 if (FormatTok.Tok.is(tok::colon)) {
588 while (FormatTok.Tok.isNot(tok::l_brace)) {
589 if (FormatTok.Tok.is(tok::semi))
590 return;
591 nextToken();
592 }
593 }
594 }
595 if (FormatTok.Tok.is(tok::l_brace))
596 parseBlock();
Manuel Klimekde768542013-01-07 18:10:23 +0000597}
598
Nico Weber1abe6ea2013-01-09 21:15:03 +0000599void UnwrappedLineParser::parseObjCProtocolList() {
600 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
601 do
602 nextToken();
603 while (!eof() && FormatTok.Tok.isNot(tok::greater));
604 nextToken(); // Skip '>'.
605}
606
607void UnwrappedLineParser::parseObjCUntilAtEnd() {
608 do {
609 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
610 nextToken();
611 addUnwrappedLine();
612 break;
613 }
614 parseStructuralElement();
615 } while (!eof());
616}
617
Nico Weber50767d82013-01-09 23:25:37 +0000618void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000619 nextToken();
620 nextToken(); // interface name
621
622 // @interface can be followed by either a base class, or a category.
623 if (FormatTok.Tok.is(tok::colon)) {
624 nextToken();
625 nextToken(); // base class name
626 } else if (FormatTok.Tok.is(tok::l_paren))
627 // Skip category, if present.
628 parseParens();
629
Nico Weber1abe6ea2013-01-09 21:15:03 +0000630 if (FormatTok.Tok.is(tok::less))
631 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000632
633 // If instance variables are present, keep the '{' on the first line too.
634 if (FormatTok.Tok.is(tok::l_brace))
635 parseBlock();
636
637 // With instance variables, this puts '}' on its own line. Without instance
638 // variables, this ends the @interface line.
639 addUnwrappedLine();
640
Nico Weber1abe6ea2013-01-09 21:15:03 +0000641 parseObjCUntilAtEnd();
642}
Nico Weber27d13672013-01-09 20:25:35 +0000643
Nico Weber1abe6ea2013-01-09 21:15:03 +0000644void UnwrappedLineParser::parseObjCProtocol() {
645 nextToken();
646 nextToken(); // protocol name
647
648 if (FormatTok.Tok.is(tok::less))
649 parseObjCProtocolList();
650
651 // Check for protocol declaration.
652 if (FormatTok.Tok.is(tok::semi)) {
653 nextToken();
654 return addUnwrappedLine();
655 }
656
657 addUnwrappedLine();
658 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000659}
660
Daniel Jasperbac016b2012-12-03 18:12:45 +0000661void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000662 if (!RootTokenInitialized)
663 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000664 // Consume trailing comments.
665 while (!eof() && FormatTok.NewlinesBefore == 0 &&
666 FormatTok.Tok.is(tok::comment)) {
667 nextToken();
668 }
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000669#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
670 FormatToken* NextToken = &Line->RootToken;
671 llvm::errs() << "Line: ";
672 while (NextToken) {
673 llvm::errs() << NextToken->Tok.getName() << " ";
674 NextToken = NextToken->Children.empty() ? NULL : &NextToken->Children[0];
675 }
676 llvm::errs() << "\n";
677#endif
Manuel Klimek526ed112013-01-09 15:25:02 +0000678 Callback.consumeUnwrappedLine(*Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000679 RootTokenInitialized = false;
Manuel Klimek526ed112013-01-09 15:25:02 +0000680 LastInCurrentLine = NULL;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000681}
682
683bool UnwrappedLineParser::eof() const {
684 return FormatTok.Tok.is(tok::eof);
685}
686
687void UnwrappedLineParser::nextToken() {
688 if (eof())
689 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000690 if (RootTokenInitialized) {
Manuel Klimek526ed112013-01-09 15:25:02 +0000691 assert(LastInCurrentLine->Children.empty());
Daniel Jasper26f7e782013-01-08 14:56:18 +0000692 LastInCurrentLine->Children.push_back(FormatTok);
693 LastInCurrentLine = &LastInCurrentLine->Children.back();
694 } else {
Manuel Klimek526ed112013-01-09 15:25:02 +0000695 Line->RootToken = FormatTok;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000696 RootTokenInitialized = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000697 LastInCurrentLine = &Line->RootToken;
698 }
699 if (MustBreakBeforeNextToken) {
700 LastInCurrentLine->MustBreakBefore = true;
701 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000702 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000703 readToken();
704}
705
706void UnwrappedLineParser::readToken() {
707 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000708 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000709 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
710 FormatTok.IsFirst)) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000711 ScopedLineState BlockState(*this);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000712 parsePPDirective();
713 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000714}
715
Daniel Jaspercd162382013-01-07 13:26:07 +0000716} // end namespace format
717} // end namespace clang