blob: 9a29ff011ae17ff76c99c36a6a06d5b4e5254845 [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();
Daniel Jaspercbb6c412013-01-16 09:10:19 +000084 Parser.Line.reset(new UnwrappedLine());
85 Parser.Line->Level = PreBlockLine->Level;
86 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
Manuel Klimekbb42bf12013-01-10 11:52:21 +000087 }
88
89 ~ScopedLineState() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +000090 if (!Parser.Line->Tokens.empty()) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +000091 Parser.addUnwrappedLine();
92 }
Daniel Jaspercbb6c412013-01-16 09:10:19 +000093 assert(Parser.Line->Tokens.empty());
Manuel Klimekbb42bf12013-01-10 11:52:21 +000094 Parser.Line.reset(PreBlockLine);
Manuel Klimekbb42bf12013-01-10 11:52:21 +000095 Parser.MustBreakBeforeNextToken = true;
96 }
97
98private:
99 UnwrappedLineParser &Parser;
100
101 UnwrappedLine *PreBlockLine;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000102};
103
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000104UnwrappedLineParser::UnwrappedLineParser(
105 clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
106 FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback)
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000107 : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), Diag(Diag),
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000108 Style(Style), Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000109}
110
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000111bool UnwrappedLineParser::parse() {
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000112#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
113 llvm::errs() << "----\n";
114#endif
Manuel Klimekd4397b92013-01-04 23:34:14 +0000115 readToken();
116 return parseFile();
117}
118
119bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +0000120 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000121 // Make sure to format the remaining tokens.
122 addUnwrappedLine();
123 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000124}
125
Manuel Klimeka5342db2013-01-06 20:07:31 +0000126bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000127 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000128 do {
129 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000130 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000131 nextToken();
132 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000133 break;
134 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000135 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000136 addUnwrappedLine();
137 break;
138 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000139 if (HasOpeningBrace) {
140 return false;
141 } else {
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000142 Diag.Report(FormatTok.Tok.getLocation(),
143 Diag.getCustomDiagID(clang::DiagnosticsEngine::Error,
Alexander Kornienko276a2092013-01-11 16:03:45 +0000144 "unexpected '}'"));
Manuel Klimeka5342db2013-01-06 20:07:31 +0000145 Error = true;
146 nextToken();
147 addUnwrappedLine();
148 }
149 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000150 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000151 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000152 break;
153 }
154 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000155 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000156}
157
Alexander Kornienko15757312012-12-06 18:03:27 +0000158bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000159 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000160 nextToken();
161
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000162 if (!FormatTok.Tok.is(tok::r_brace)) {
163 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000164
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000165 Line->Level += AddLevels;
166 parseLevel(/*HasOpeningBrace=*/true);
167 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000168
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000169 if (!FormatTok.Tok.is(tok::r_brace))
170 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000171
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000172 }
Manuel Klimekde768542013-01-07 18:10:23 +0000173 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000174 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000175}
176
177void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000178 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000179 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000180 nextToken();
181
Manuel Klimeka080a182013-01-02 16:30:12 +0000182 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
183 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000184 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000185 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000186
Manuel Klimekd4397b92013-01-04 23:34:14 +0000187 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
188 case tok::pp_define:
189 parsePPDefine();
190 break;
191 default:
192 parsePPUnknown();
193 break;
194 }
195}
196
197void UnwrappedLineParser::parsePPDefine() {
198 nextToken();
199
200 if (FormatTok.Tok.getKind() != tok::identifier) {
201 parsePPUnknown();
202 return;
203 }
204 nextToken();
205 if (FormatTok.Tok.getKind() == tok::l_paren) {
206 parseParens();
207 }
208 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000209 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000210
211 // Errors during a preprocessor directive can only affect the layout of the
212 // preprocessor directive, and thus we ignore them. An alternative approach
213 // would be to use the same approach we use on the file level (no
214 // re-indentation if there was a structural error) within the macro
215 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000216 parseFile();
217}
218
219void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000220 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000221 nextToken();
222 } while (!eof());
223 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000224}
225
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000226void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000227 // Consume leading line comments, e.g. for branches without compounds.
228 while (FormatTok.Tok.is(tok::comment)) {
229 nextToken();
230 addUnwrappedLine();
231 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000232}
233
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000234void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000235 assert(!FormatTok.Tok.is(tok::l_brace));
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000236 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000237
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000238 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000239 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000240 case tok::at:
241 nextToken();
242 switch (FormatTok.Tok.getObjCKeywordID()) {
243 case tok::objc_public:
244 case tok::objc_protected:
245 case tok::objc_package:
246 case tok::objc_private:
247 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000248 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000249 case tok::objc_implementation:
250 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000251 case tok::objc_protocol:
252 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000253 case tok::objc_end:
254 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000255 case tok::objc_optional:
256 case tok::objc_required:
257 nextToken();
258 addUnwrappedLine();
259 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000260 default:
261 break;
262 }
263 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000264 case tok::kw_namespace:
265 parseNamespace();
266 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000267 case tok::kw_inline:
268 nextToken();
269 TokenNumber++;
270 if (FormatTok.Tok.is(tok::kw_namespace)) {
271 parseNamespace();
272 return;
273 }
274 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000275 case tok::kw_public:
276 case tok::kw_protected:
277 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000278 parseAccessSpecifier();
279 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000280 case tok::kw_if:
281 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000282 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000283 case tok::kw_for:
284 case tok::kw_while:
285 parseForOrWhileLoop();
286 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000287 case tok::kw_do:
288 parseDoWhile();
289 return;
290 case tok::kw_switch:
291 parseSwitch();
292 return;
293 case tok::kw_default:
294 nextToken();
295 parseLabel();
296 return;
297 case tok::kw_case:
298 parseCaseLabel();
299 return;
300 default:
301 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000302 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000303 do {
304 ++TokenNumber;
305 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000306 case tok::kw_enum:
307 parseEnum();
308 return;
Daniel Jasper17746032013-01-13 14:39:04 +0000309 case tok::kw_struct: // fallthrough
310 case tok::kw_union: // fallthrough
Manuel Klimekde768542013-01-07 18:10:23 +0000311 case tok::kw_class:
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000312 parseRecord();
313 // A record declaration or definition is always the start of a structural
314 // element.
315 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000316 case tok::semi:
317 nextToken();
318 addUnwrappedLine();
319 return;
320 case tok::l_paren:
321 parseParens();
322 break;
323 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000324 // A block outside of parentheses must be the last part of a
325 // structural element.
326 // FIXME: Figure out cases where this is not true, and add projections for
327 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000328 parseBlock();
329 addUnwrappedLine();
330 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000331 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000332 nextToken();
333 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
334 parseLabel();
335 return;
336 }
337 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000338 case tok::equal:
339 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000340 if (FormatTok.Tok.is(tok::l_brace)) {
341 parseBracedList();
342 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000343 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000344 default:
345 nextToken();
346 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000347 }
348 } while (!eof());
349}
350
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000351void UnwrappedLineParser::parseBracedList() {
352 nextToken();
353
354 do {
355 switch (FormatTok.Tok.getKind()) {
356 case tok::l_brace:
357 parseBracedList();
358 break;
359 case tok::r_brace:
360 nextToken();
361 return;
362 default:
363 nextToken();
364 break;
365 }
366 } while (!eof());
367}
368
Daniel Jasperbac016b2012-12-03 18:12:45 +0000369void UnwrappedLineParser::parseParens() {
370 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
371 nextToken();
372 do {
373 switch (FormatTok.Tok.getKind()) {
374 case tok::l_paren:
375 parseParens();
376 break;
377 case tok::r_paren:
378 nextToken();
379 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000380 case tok::l_brace:
381 {
382 nextToken();
383 ScopedLineState LineState(*this);
384 Line->Level += 1;
385 parseLevel(/*HasOpeningBrace=*/true);
386 Line->Level -= 1;
387 }
388 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000389 default:
390 nextToken();
391 break;
392 }
393 } while (!eof());
394}
395
396void UnwrappedLineParser::parseIfThenElse() {
397 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
398 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000399 if (FormatTok.Tok.is(tok::l_paren))
400 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000401 bool NeedsUnwrappedLine = false;
402 if (FormatTok.Tok.is(tok::l_brace)) {
403 parseBlock();
404 NeedsUnwrappedLine = true;
405 } else {
406 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000407 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000408 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000409 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000410 }
411 if (FormatTok.Tok.is(tok::kw_else)) {
412 nextToken();
413 if (FormatTok.Tok.is(tok::l_brace)) {
414 parseBlock();
415 addUnwrappedLine();
416 } else if (FormatTok.Tok.is(tok::kw_if)) {
417 parseIfThenElse();
418 } else {
419 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000420 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000421 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000422 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000423 }
424 } else if (NeedsUnwrappedLine) {
425 addUnwrappedLine();
426 }
427}
428
Alexander Kornienko15757312012-12-06 18:03:27 +0000429void UnwrappedLineParser::parseNamespace() {
430 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
431 nextToken();
432 if (FormatTok.Tok.is(tok::identifier))
433 nextToken();
434 if (FormatTok.Tok.is(tok::l_brace)) {
435 parseBlock(0);
436 addUnwrappedLine();
437 }
438 // FIXME: Add error handling.
439}
440
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000441void UnwrappedLineParser::parseForOrWhileLoop() {
442 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
443 "'for' or 'while' expected");
444 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000445 if (FormatTok.Tok.is(tok::l_paren))
446 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000447 if (FormatTok.Tok.is(tok::l_brace)) {
448 parseBlock();
449 addUnwrappedLine();
450 } else {
451 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000452 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000453 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000454 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000455 }
456}
457
Daniel Jasperbac016b2012-12-03 18:12:45 +0000458void UnwrappedLineParser::parseDoWhile() {
459 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
460 nextToken();
461 if (FormatTok.Tok.is(tok::l_brace)) {
462 parseBlock();
463 } else {
464 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000465 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000466 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000467 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000468 }
469
Alexander Kornienko393b0082012-12-04 15:40:36 +0000470 // FIXME: Add error handling.
471 if (!FormatTok.Tok.is(tok::kw_while)) {
472 addUnwrappedLine();
473 return;
474 }
475
Daniel Jasperbac016b2012-12-03 18:12:45 +0000476 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000477 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000478}
479
480void UnwrappedLineParser::parseLabel() {
481 // FIXME: remove all asserts.
482 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
483 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000484 unsigned OldLineLevel = Line->Level;
485 if (Line->Level > 0)
486 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000487 if (FormatTok.Tok.is(tok::l_brace)) {
488 parseBlock();
489 }
490 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000491 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000492}
493
494void UnwrappedLineParser::parseCaseLabel() {
495 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
496 // FIXME: fix handling of complex expressions here.
497 do {
498 nextToken();
499 } while (!eof() && !FormatTok.Tok.is(tok::colon));
500 parseLabel();
501}
502
503void UnwrappedLineParser::parseSwitch() {
504 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
505 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000506 if (FormatTok.Tok.is(tok::l_paren))
507 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000508 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000509 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000510 addUnwrappedLine();
511 } else {
512 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000513 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000514 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000515 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000516 }
517}
518
519void UnwrappedLineParser::parseAccessSpecifier() {
520 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000521 // Otherwise, we don't know what it is, and we'd better keep the next token.
522 if (FormatTok.Tok.is(tok::colon))
523 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000524 addUnwrappedLine();
525}
526
527void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000528 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000529 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000530 switch (FormatTok.Tok.getKind()) {
531 case tok::l_brace:
532 nextToken();
533 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000534 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000535 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000536 break;
537 case tok::l_paren:
538 parseParens();
539 break;
540 case tok::comma:
541 nextToken();
542 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000543 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000544 break;
545 case tok::r_brace:
546 if (HasContents)
547 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000548 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000549 nextToken();
550 break;
551 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000552 nextToken();
553 addUnwrappedLine();
554 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000555 default:
556 HasContents = true;
557 nextToken();
558 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000559 }
560 } while (!eof());
561}
562
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000563void UnwrappedLineParser::parseRecord() {
Manuel Klimekde768542013-01-07 18:10:23 +0000564 nextToken();
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000565 if (FormatTok.Tok.is(tok::identifier) ||
566 FormatTok.Tok.is(tok::kw___attribute) ||
567 FormatTok.Tok.is(tok::kw___declspec)) {
568 nextToken();
569 // We can have macros or attributes in between 'class' and the class name.
570 if (FormatTok.Tok.is(tok::l_paren)) {
571 parseParens();
Manuel Klimekde768542013-01-07 18:10:23 +0000572 }
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000573 if (FormatTok.Tok.is(tok::identifier))
574 nextToken();
575
576 if (FormatTok.Tok.is(tok::colon)) {
577 while (FormatTok.Tok.isNot(tok::l_brace)) {
578 if (FormatTok.Tok.is(tok::semi))
579 return;
580 nextToken();
581 }
582 }
583 }
584 if (FormatTok.Tok.is(tok::l_brace))
585 parseBlock();
Manuel Klimekde768542013-01-07 18:10:23 +0000586}
587
Nico Weber1abe6ea2013-01-09 21:15:03 +0000588void UnwrappedLineParser::parseObjCProtocolList() {
589 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
590 do
591 nextToken();
592 while (!eof() && FormatTok.Tok.isNot(tok::greater));
593 nextToken(); // Skip '>'.
594}
595
596void UnwrappedLineParser::parseObjCUntilAtEnd() {
597 do {
598 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
599 nextToken();
600 addUnwrappedLine();
601 break;
602 }
603 parseStructuralElement();
604 } while (!eof());
605}
606
Nico Weber50767d82013-01-09 23:25:37 +0000607void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000608 nextToken();
609 nextToken(); // interface name
610
611 // @interface can be followed by either a base class, or a category.
612 if (FormatTok.Tok.is(tok::colon)) {
613 nextToken();
614 nextToken(); // base class name
615 } else if (FormatTok.Tok.is(tok::l_paren))
616 // Skip category, if present.
617 parseParens();
618
Nico Weber1abe6ea2013-01-09 21:15:03 +0000619 if (FormatTok.Tok.is(tok::less))
620 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000621
622 // If instance variables are present, keep the '{' on the first line too.
623 if (FormatTok.Tok.is(tok::l_brace))
624 parseBlock();
625
626 // With instance variables, this puts '}' on its own line. Without instance
627 // variables, this ends the @interface line.
628 addUnwrappedLine();
629
Nico Weber1abe6ea2013-01-09 21:15:03 +0000630 parseObjCUntilAtEnd();
631}
Nico Weber27d13672013-01-09 20:25:35 +0000632
Nico Weber1abe6ea2013-01-09 21:15:03 +0000633void UnwrappedLineParser::parseObjCProtocol() {
634 nextToken();
635 nextToken(); // protocol name
636
637 if (FormatTok.Tok.is(tok::less))
638 parseObjCProtocolList();
639
640 // Check for protocol declaration.
641 if (FormatTok.Tok.is(tok::semi)) {
642 nextToken();
643 return addUnwrappedLine();
644 }
645
646 addUnwrappedLine();
647 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000648}
649
Daniel Jasperbac016b2012-12-03 18:12:45 +0000650void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000651 if (Line->Tokens.empty())
Daniel Jasper26f7e782013-01-08 14:56:18 +0000652 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000653 // Consume trailing comments.
654 while (!eof() && FormatTok.NewlinesBefore == 0 &&
655 FormatTok.Tok.is(tok::comment)) {
656 nextToken();
657 }
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000658#ifdef UNWRAPPED_LINE_PARSER_DEBUG_OUTPUT
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000659 llvm::errs() << "Line: ";
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000660 for (std::list<FormatToken>::iterator I = Line->Tokens.begin(),
661 E = Line->Tokens.end();
662 I != E; ++I) {
663 llvm::errs() << I->Tok.getName() << " ";
664
Manuel Klimek4c60fc62013-01-10 10:05:08 +0000665 }
666 llvm::errs() << "\n";
667#endif
Manuel Klimek526ed112013-01-09 15:25:02 +0000668 Callback.consumeUnwrappedLine(*Line);
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000669 Line->Tokens.clear();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000670}
671
672bool UnwrappedLineParser::eof() const {
673 return FormatTok.Tok.is(tok::eof);
674}
675
676void UnwrappedLineParser::nextToken() {
677 if (eof())
678 return;
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000679 Line->Tokens.push_back(FormatTok);
Manuel Klimek526ed112013-01-09 15:25:02 +0000680 if (MustBreakBeforeNextToken) {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000681 Line->Tokens.back().MustBreakBefore = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000682 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000683 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000684 readToken();
685}
686
687void UnwrappedLineParser::readToken() {
688 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000689 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000690 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
691 FormatTok.IsFirst)) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000692 ScopedLineState BlockState(*this);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000693 parsePPDirective();
694 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000695}
696
Daniel Jaspercd162382013-01-07 13:26:07 +0000697} // end namespace format
698} // end namespace clang