blob: e8b334bb3d8fe01d7e3f049c5053abbf2360d1fb [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
Manuel Klimek8fa37992013-01-16 12:31:12 +000019#define DEBUG_TYPE "format-parser"
Daniel Jasperbac016b2012-12-03 18:12:45 +000020
Manuel Klimek8fa37992013-01-16 12:31:12 +000021#include "clang/Basic/Diagnostic.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/raw_ostream.h"
24#include "UnwrappedLineParser.h"
25
26// Uncomment to get debug output from tests:
27// #define DEBUG_WITH_TYPE(T, X) do { X; } while(0)
Manuel Klimek4c60fc62013-01-10 10:05:08 +000028
Daniel Jasperbac016b2012-12-03 18:12:45 +000029namespace clang {
30namespace format {
31
Manuel Klimekd4397b92013-01-04 23:34:14 +000032class ScopedMacroState : public FormatTokenSource {
33public:
34 ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
35 FormatToken &ResetToken)
36 : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
Manuel Klimekc37b4d62013-01-05 22:14:16 +000037 PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource) {
Manuel Klimekd4397b92013-01-04 23:34:14 +000038 TokenSource = this;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000039 Line.Level = 0;
Manuel Klimekd4397b92013-01-04 23:34:14 +000040 Line.InPPDirective = true;
41 }
42
43 ~ScopedMacroState() {
44 TokenSource = PreviousTokenSource;
45 ResetToken = Token;
46 Line.InPPDirective = false;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000047 Line.Level = PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000048 }
49
50 virtual FormatToken getNextToken() {
Manuel Klimekdd5b1012013-01-07 10:03:37 +000051 // The \c UnwrappedLineParser guards against this by never calling
52 // \c getNextToken() after it has encountered the first eof token.
53 assert(!eof());
Manuel Klimekd4397b92013-01-04 23:34:14 +000054 Token = PreviousTokenSource->getNextToken();
55 if (eof())
56 return createEOF();
57 return Token;
58 }
59
60private:
61 bool eof() {
62 return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline;
63 }
64
65 FormatToken createEOF() {
66 FormatToken FormatTok;
67 FormatTok.Tok.startToken();
68 FormatTok.Tok.setKind(tok::eof);
69 return FormatTok;
70 }
71
72 UnwrappedLine &Line;
73 FormatTokenSource *&TokenSource;
74 FormatToken &ResetToken;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000075 unsigned PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000076 FormatTokenSource *PreviousTokenSource;
77
78 FormatToken Token;
79};
80
Manuel Klimekbb42bf12013-01-10 11:52:21 +000081class ScopedLineState {
82public:
83 ScopedLineState(UnwrappedLineParser &Parser) : Parser(Parser) {
84 PreBlockLine = Parser.Line.take();
Daniel Jaspercbb6c412013-01-16 09:10:19 +000085 Parser.Line.reset(new UnwrappedLine());
86 Parser.Line->Level = PreBlockLine->Level;
87 Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
Manuel Klimekbb42bf12013-01-10 11:52:21 +000088 }
89
90 ~ScopedLineState() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +000091 if (!Parser.Line->Tokens.empty()) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +000092 Parser.addUnwrappedLine();
93 }
Daniel Jaspercbb6c412013-01-16 09:10:19 +000094 assert(Parser.Line->Tokens.empty());
Manuel Klimekbb42bf12013-01-10 11:52:21 +000095 Parser.Line.reset(PreBlockLine);
Manuel Klimekbb42bf12013-01-10 11:52:21 +000096 Parser.MustBreakBeforeNextToken = true;
97 }
98
99private:
100 UnwrappedLineParser &Parser;
101
102 UnwrappedLine *PreBlockLine;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000103};
104
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000105UnwrappedLineParser::UnwrappedLineParser(
106 clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
107 FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback)
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000108 : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), Diag(Diag),
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000109 Style(Style), Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000110}
111
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000112bool UnwrappedLineParser::parse() {
Manuel Klimek8fa37992013-01-16 12:31:12 +0000113 DEBUG(llvm::dbgs() << "----\n");
Manuel Klimekd4397b92013-01-04 23:34:14 +0000114 readToken();
115 return parseFile();
116}
117
118bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +0000119 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000120 // Make sure to format the remaining tokens.
121 addUnwrappedLine();
122 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000123}
124
Manuel Klimeka5342db2013-01-06 20:07:31 +0000125bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000126 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000127 do {
128 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +0000129 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000130 nextToken();
131 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000132 break;
133 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000134 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000135 addUnwrappedLine();
136 break;
137 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000138 if (HasOpeningBrace) {
139 return false;
140 } else {
Alexander Kornienko3048aea2013-01-10 15:05:09 +0000141 Diag.Report(FormatTok.Tok.getLocation(),
142 Diag.getCustomDiagID(clang::DiagnosticsEngine::Error,
Alexander Kornienko276a2092013-01-11 16:03:45 +0000143 "unexpected '}'"));
Manuel Klimeka5342db2013-01-06 20:07:31 +0000144 Error = true;
145 nextToken();
146 addUnwrappedLine();
147 }
148 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000149 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000150 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000151 break;
152 }
153 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000154 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000155}
156
Alexander Kornienko15757312012-12-06 18:03:27 +0000157bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000158 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000159 nextToken();
160
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000161 if (!FormatTok.Tok.is(tok::r_brace)) {
162 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000163
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000164 Line->Level += AddLevels;
165 parseLevel(/*HasOpeningBrace=*/true);
166 Line->Level -= AddLevels;
Alexander Kornienko15757312012-12-06 18:03:27 +0000167
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000168 if (!FormatTok.Tok.is(tok::r_brace))
169 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000170
Manuel Klimek36fab8d2013-01-10 13:24:24 +0000171 }
Manuel Klimekde768542013-01-07 18:10:23 +0000172 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000173 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000174}
175
176void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000177 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimek526ed112013-01-09 15:25:02 +0000178 ScopedMacroState MacroState(*Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000179 nextToken();
180
Manuel Klimeka080a182013-01-02 16:30:12 +0000181 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
182 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000183 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000184 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000185
Manuel Klimekd4397b92013-01-04 23:34:14 +0000186 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
187 case tok::pp_define:
188 parsePPDefine();
189 break;
190 default:
191 parsePPUnknown();
192 break;
193 }
194}
195
196void UnwrappedLineParser::parsePPDefine() {
197 nextToken();
198
199 if (FormatTok.Tok.getKind() != tok::identifier) {
200 parsePPUnknown();
201 return;
202 }
203 nextToken();
204 if (FormatTok.Tok.getKind() == tok::l_paren) {
205 parseParens();
206 }
207 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000208 Line->Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000209
210 // Errors during a preprocessor directive can only affect the layout of the
211 // preprocessor directive, and thus we ignore them. An alternative approach
212 // would be to use the same approach we use on the file level (no
213 // re-indentation if there was a structural error) within the macro
214 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000215 parseFile();
216}
217
218void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000219 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000220 nextToken();
221 } while (!eof());
222 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000223}
224
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000225void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000226 // Consume leading line comments, e.g. for branches without compounds.
227 while (FormatTok.Tok.is(tok::comment)) {
228 nextToken();
229 addUnwrappedLine();
230 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000231}
232
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000233void UnwrappedLineParser::parseStructuralElement() {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000234 assert(!FormatTok.Tok.is(tok::l_brace));
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000235 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000236
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000237 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000238 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000239 case tok::at:
240 nextToken();
241 switch (FormatTok.Tok.getObjCKeywordID()) {
242 case tok::objc_public:
243 case tok::objc_protected:
244 case tok::objc_package:
245 case tok::objc_private:
246 return parseAccessSpecifier();
Nico Weber27d13672013-01-09 20:25:35 +0000247 case tok::objc_interface:
Nico Weber50767d82013-01-09 23:25:37 +0000248 case tok::objc_implementation:
249 return parseObjCInterfaceOrImplementation();
Nico Weber1abe6ea2013-01-09 21:15:03 +0000250 case tok::objc_protocol:
251 return parseObjCProtocol();
Nico Weber049c4472013-01-09 21:42:32 +0000252 case tok::objc_end:
253 return; // Handled by the caller.
Nico Weberb530fa32013-01-10 00:25:19 +0000254 case tok::objc_optional:
255 case tok::objc_required:
256 nextToken();
257 addUnwrappedLine();
258 return;
Nico Weber6092d4e2013-01-07 19:05:19 +0000259 default:
260 break;
261 }
262 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000263 case tok::kw_namespace:
264 parseNamespace();
265 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000266 case tok::kw_inline:
267 nextToken();
268 TokenNumber++;
269 if (FormatTok.Tok.is(tok::kw_namespace)) {
270 parseNamespace();
271 return;
272 }
273 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000274 case tok::kw_public:
275 case tok::kw_protected:
276 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000277 parseAccessSpecifier();
278 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000279 case tok::kw_if:
280 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000281 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000282 case tok::kw_for:
283 case tok::kw_while:
284 parseForOrWhileLoop();
285 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000286 case tok::kw_do:
287 parseDoWhile();
288 return;
289 case tok::kw_switch:
290 parseSwitch();
291 return;
292 case tok::kw_default:
293 nextToken();
294 parseLabel();
295 return;
296 case tok::kw_case:
297 parseCaseLabel();
298 return;
299 default:
300 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000301 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000302 do {
303 ++TokenNumber;
304 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000305 case tok::kw_enum:
306 parseEnum();
307 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000308 case tok::kw_struct:
309 case tok::kw_union:
Manuel Klimekde768542013-01-07 18:10:23 +0000310 case tok::kw_class:
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000311 parseRecord();
312 // A record declaration or definition is always the start of a structural
313 // element.
314 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000315 case tok::semi:
316 nextToken();
317 addUnwrappedLine();
318 return;
Alexander Kornienkod8818752013-01-16 11:43:46 +0000319 case tok::r_brace:
320 addUnwrappedLine();
321 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000322 case tok::l_paren:
323 parseParens();
324 break;
325 case tok::l_brace:
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000326 // A block outside of parentheses must be the last part of a
327 // structural element.
328 // FIXME: Figure out cases where this is not true, and add projections for
329 // them (the one we know is missing are lambdas).
Daniel Jasperbac016b2012-12-03 18:12:45 +0000330 parseBlock();
331 addUnwrappedLine();
332 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000333 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000334 nextToken();
335 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
336 parseLabel();
337 return;
338 }
339 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000340 case tok::equal:
341 nextToken();
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000342 if (FormatTok.Tok.is(tok::l_brace)) {
343 parseBracedList();
344 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000345 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000346 default:
347 nextToken();
348 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000349 }
350 } while (!eof());
351}
352
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000353void UnwrappedLineParser::parseBracedList() {
354 nextToken();
355
356 do {
357 switch (FormatTok.Tok.getKind()) {
358 case tok::l_brace:
359 parseBracedList();
360 break;
361 case tok::r_brace:
362 nextToken();
363 return;
364 default:
365 nextToken();
366 break;
367 }
368 } while (!eof());
369}
370
Daniel Jasperbac016b2012-12-03 18:12:45 +0000371void UnwrappedLineParser::parseParens() {
372 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
373 nextToken();
374 do {
375 switch (FormatTok.Tok.getKind()) {
376 case tok::l_paren:
377 parseParens();
378 break;
379 case tok::r_paren:
380 nextToken();
381 return;
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000382 case tok::l_brace:
383 {
384 nextToken();
385 ScopedLineState LineState(*this);
386 Line->Level += 1;
387 parseLevel(/*HasOpeningBrace=*/true);
388 Line->Level -= 1;
389 }
390 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000391 default:
392 nextToken();
393 break;
394 }
395 } while (!eof());
396}
397
398void UnwrappedLineParser::parseIfThenElse() {
399 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
400 nextToken();
Manuel Klimekd4658432013-01-11 18:28:36 +0000401 if (FormatTok.Tok.is(tok::l_paren))
402 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000403 bool NeedsUnwrappedLine = false;
404 if (FormatTok.Tok.is(tok::l_brace)) {
405 parseBlock();
406 NeedsUnwrappedLine = true;
407 } else {
408 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000409 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000410 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000411 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000412 }
413 if (FormatTok.Tok.is(tok::kw_else)) {
414 nextToken();
415 if (FormatTok.Tok.is(tok::l_brace)) {
416 parseBlock();
417 addUnwrappedLine();
418 } else if (FormatTok.Tok.is(tok::kw_if)) {
419 parseIfThenElse();
420 } else {
421 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000422 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000423 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000424 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000425 }
426 } else if (NeedsUnwrappedLine) {
427 addUnwrappedLine();
428 }
429}
430
Alexander Kornienko15757312012-12-06 18:03:27 +0000431void UnwrappedLineParser::parseNamespace() {
432 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
433 nextToken();
434 if (FormatTok.Tok.is(tok::identifier))
435 nextToken();
436 if (FormatTok.Tok.is(tok::l_brace)) {
437 parseBlock(0);
438 addUnwrappedLine();
439 }
440 // FIXME: Add error handling.
441}
442
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000443void UnwrappedLineParser::parseForOrWhileLoop() {
444 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
445 "'for' or 'while' expected");
446 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000447 if (FormatTok.Tok.is(tok::l_paren))
448 parseParens();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000449 if (FormatTok.Tok.is(tok::l_brace)) {
450 parseBlock();
451 addUnwrappedLine();
452 } else {
453 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000454 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000455 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000456 --Line->Level;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000457 }
458}
459
Daniel Jasperbac016b2012-12-03 18:12:45 +0000460void UnwrappedLineParser::parseDoWhile() {
461 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
462 nextToken();
463 if (FormatTok.Tok.is(tok::l_brace)) {
464 parseBlock();
465 } else {
466 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000467 ++Line->Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000468 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000469 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000470 }
471
Alexander Kornienko393b0082012-12-04 15:40:36 +0000472 // FIXME: Add error handling.
473 if (!FormatTok.Tok.is(tok::kw_while)) {
474 addUnwrappedLine();
475 return;
476 }
477
Daniel Jasperbac016b2012-12-03 18:12:45 +0000478 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000479 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000480}
481
482void UnwrappedLineParser::parseLabel() {
483 // FIXME: remove all asserts.
484 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
485 nextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000486 unsigned OldLineLevel = Line->Level;
487 if (Line->Level > 0)
488 --Line->Level;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000489 if (FormatTok.Tok.is(tok::l_brace)) {
490 parseBlock();
491 }
492 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000493 Line->Level = OldLineLevel;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000494}
495
496void UnwrappedLineParser::parseCaseLabel() {
497 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
498 // FIXME: fix handling of complex expressions here.
499 do {
500 nextToken();
501 } while (!eof() && !FormatTok.Tok.is(tok::colon));
502 parseLabel();
503}
504
505void UnwrappedLineParser::parseSwitch() {
506 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
507 nextToken();
Manuel Klimek6eca03f2013-01-11 19:23:05 +0000508 if (FormatTok.Tok.is(tok::l_paren))
509 parseParens();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000510 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000511 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000512 addUnwrappedLine();
513 } else {
514 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000515 Line->Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000516 parseStructuralElement();
Manuel Klimek526ed112013-01-09 15:25:02 +0000517 Line->Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000518 }
519}
520
521void UnwrappedLineParser::parseAccessSpecifier() {
522 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000523 // Otherwise, we don't know what it is, and we'd better keep the next token.
524 if (FormatTok.Tok.is(tok::colon))
525 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000526 addUnwrappedLine();
527}
528
529void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000530 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000531 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000532 switch (FormatTok.Tok.getKind()) {
533 case tok::l_brace:
534 nextToken();
535 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000536 ++Line->Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000537 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000538 break;
539 case tok::l_paren:
540 parseParens();
541 break;
542 case tok::comma:
543 nextToken();
544 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000545 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000546 break;
547 case tok::r_brace:
548 if (HasContents)
549 addUnwrappedLine();
Manuel Klimek526ed112013-01-09 15:25:02 +0000550 --Line->Level;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000551 nextToken();
552 break;
553 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000554 nextToken();
555 addUnwrappedLine();
556 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000557 default:
558 HasContents = true;
559 nextToken();
560 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000561 }
562 } while (!eof());
563}
564
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000565void UnwrappedLineParser::parseRecord() {
Manuel Klimekde768542013-01-07 18:10:23 +0000566 nextToken();
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000567 if (FormatTok.Tok.is(tok::identifier) ||
568 FormatTok.Tok.is(tok::kw___attribute) ||
569 FormatTok.Tok.is(tok::kw___declspec)) {
570 nextToken();
571 // We can have macros or attributes in between 'class' and the class name.
572 if (FormatTok.Tok.is(tok::l_paren)) {
573 parseParens();
Manuel Klimekde768542013-01-07 18:10:23 +0000574 }
Manuel Klimek47ea7f62013-01-15 13:38:33 +0000575 if (FormatTok.Tok.is(tok::identifier))
576 nextToken();
577
578 if (FormatTok.Tok.is(tok::colon)) {
579 while (FormatTok.Tok.isNot(tok::l_brace)) {
580 if (FormatTok.Tok.is(tok::semi))
581 return;
582 nextToken();
583 }
584 }
585 }
586 if (FormatTok.Tok.is(tok::l_brace))
587 parseBlock();
Manuel Klimekde768542013-01-07 18:10:23 +0000588}
589
Nico Weber1abe6ea2013-01-09 21:15:03 +0000590void UnwrappedLineParser::parseObjCProtocolList() {
591 assert(FormatTok.Tok.is(tok::less) && "'<' expected.");
592 do
593 nextToken();
594 while (!eof() && FormatTok.Tok.isNot(tok::greater));
595 nextToken(); // Skip '>'.
596}
597
598void UnwrappedLineParser::parseObjCUntilAtEnd() {
599 do {
600 if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
601 nextToken();
602 addUnwrappedLine();
603 break;
604 }
605 parseStructuralElement();
606 } while (!eof());
607}
608
Nico Weber50767d82013-01-09 23:25:37 +0000609void UnwrappedLineParser::parseObjCInterfaceOrImplementation() {
Nico Weber27d13672013-01-09 20:25:35 +0000610 nextToken();
611 nextToken(); // interface name
612
613 // @interface can be followed by either a base class, or a category.
614 if (FormatTok.Tok.is(tok::colon)) {
615 nextToken();
616 nextToken(); // base class name
617 } else if (FormatTok.Tok.is(tok::l_paren))
618 // Skip category, if present.
619 parseParens();
620
Nico Weber1abe6ea2013-01-09 21:15:03 +0000621 if (FormatTok.Tok.is(tok::less))
622 parseObjCProtocolList();
Nico Weber27d13672013-01-09 20:25:35 +0000623
624 // If instance variables are present, keep the '{' on the first line too.
625 if (FormatTok.Tok.is(tok::l_brace))
626 parseBlock();
627
628 // With instance variables, this puts '}' on its own line. Without instance
629 // variables, this ends the @interface line.
630 addUnwrappedLine();
631
Nico Weber1abe6ea2013-01-09 21:15:03 +0000632 parseObjCUntilAtEnd();
633}
Nico Weber27d13672013-01-09 20:25:35 +0000634
Nico Weber1abe6ea2013-01-09 21:15:03 +0000635void UnwrappedLineParser::parseObjCProtocol() {
636 nextToken();
637 nextToken(); // protocol name
638
639 if (FormatTok.Tok.is(tok::less))
640 parseObjCProtocolList();
641
642 // Check for protocol declaration.
643 if (FormatTok.Tok.is(tok::semi)) {
644 nextToken();
645 return addUnwrappedLine();
646 }
647
648 addUnwrappedLine();
649 parseObjCUntilAtEnd();
Nico Weber27d13672013-01-09 20:25:35 +0000650}
651
Daniel Jasperbac016b2012-12-03 18:12:45 +0000652void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000653 if (Line->Tokens.empty())
Daniel Jasper26f7e782013-01-08 14:56:18 +0000654 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000655 // Consume trailing comments.
656 while (!eof() && FormatTok.NewlinesBefore == 0 &&
657 FormatTok.Tok.is(tok::comment)) {
658 nextToken();
659 }
Manuel Klimek8fa37992013-01-16 12:31:12 +0000660 DEBUG({
661 llvm::dbgs() << "Line: ";
662 for (std::list<FormatToken>::iterator I = Line->Tokens.begin(),
663 E = Line->Tokens.end();
664 I != E; ++I) {
665 llvm::dbgs() << I->Tok.getName() << " ";
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000666
Manuel Klimek8fa37992013-01-16 12:31:12 +0000667 }
668 llvm::dbgs() << "\n";
669 });
Manuel Klimek526ed112013-01-09 15:25:02 +0000670 Callback.consumeUnwrappedLine(*Line);
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000671 Line->Tokens.clear();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000672}
673
674bool UnwrappedLineParser::eof() const {
675 return FormatTok.Tok.is(tok::eof);
676}
677
678void UnwrappedLineParser::nextToken() {
679 if (eof())
680 return;
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000681 Line->Tokens.push_back(FormatTok);
Manuel Klimek526ed112013-01-09 15:25:02 +0000682 if (MustBreakBeforeNextToken) {
Daniel Jaspercbb6c412013-01-16 09:10:19 +0000683 Line->Tokens.back().MustBreakBefore = true;
Manuel Klimek526ed112013-01-09 15:25:02 +0000684 MustBreakBeforeNextToken = false;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000685 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000686 readToken();
687}
688
689void UnwrappedLineParser::readToken() {
690 FormatTok = Tokens->getNextToken();
Manuel Klimek526ed112013-01-09 15:25:02 +0000691 while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000692 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
693 FormatTok.IsFirst)) {
Manuel Klimekbb42bf12013-01-10 11:52:21 +0000694 ScopedLineState BlockState(*this);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000695 parsePPDirective();
696 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000697}
698
Daniel Jaspercd162382013-01-07 13:26:07 +0000699} // end namespace format
700} // end namespace clang