blob: d7220259b7e7feaaab30e6d2cc79581dba5c908f [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"
Daniel Jasperbac016b2012-12-03 18:12:45 +000020#include "llvm/Support/raw_ostream.h"
21
22namespace clang {
23namespace format {
24
Manuel Klimekd4397b92013-01-04 23:34:14 +000025class ScopedMacroState : public FormatTokenSource {
26public:
27 ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
28 FormatToken &ResetToken)
29 : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
Manuel Klimekc37b4d62013-01-05 22:14:16 +000030 PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource) {
Manuel Klimekd4397b92013-01-04 23:34:14 +000031 TokenSource = this;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000032 Line.Level = 0;
Manuel Klimekd4397b92013-01-04 23:34:14 +000033 Line.InPPDirective = true;
34 }
35
36 ~ScopedMacroState() {
37 TokenSource = PreviousTokenSource;
38 ResetToken = Token;
39 Line.InPPDirective = false;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000040 Line.Level = PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000041 }
42
43 virtual FormatToken getNextToken() {
Manuel Klimekdd5b1012013-01-07 10:03:37 +000044 // The \c UnwrappedLineParser guards against this by never calling
45 // \c getNextToken() after it has encountered the first eof token.
46 assert(!eof());
Manuel Klimekd4397b92013-01-04 23:34:14 +000047 Token = PreviousTokenSource->getNextToken();
48 if (eof())
49 return createEOF();
50 return Token;
51 }
52
53private:
54 bool eof() {
55 return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline;
56 }
57
58 FormatToken createEOF() {
59 FormatToken FormatTok;
60 FormatTok.Tok.startToken();
61 FormatTok.Tok.setKind(tok::eof);
62 return FormatTok;
63 }
64
65 UnwrappedLine &Line;
66 FormatTokenSource *&TokenSource;
67 FormatToken &ResetToken;
Manuel Klimekc37b4d62013-01-05 22:14:16 +000068 unsigned PreviousLineLevel;
Manuel Klimekd4397b92013-01-04 23:34:14 +000069 FormatTokenSource *PreviousTokenSource;
70
71 FormatToken Token;
72};
73
Alexander Kornienko469a21b2012-12-07 16:15:44 +000074UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
75 FormatTokenSource &Tokens,
Daniel Jasperbac016b2012-12-03 18:12:45 +000076 UnwrappedLineConsumer &Callback)
Manuel Klimekd4397b92013-01-04 23:34:14 +000077 : Style(Style), Tokens(&Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000078}
79
Alexander Kornienkocff563c2012-12-04 17:27:50 +000080bool UnwrappedLineParser::parse() {
Manuel Klimekd4397b92013-01-04 23:34:14 +000081 readToken();
82 return parseFile();
83}
84
85bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +000086 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +000087 // Make sure to format the remaining tokens.
88 addUnwrappedLine();
89 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +000090}
91
Manuel Klimeka5342db2013-01-06 20:07:31 +000092bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +000093 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +000094 do {
95 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000096 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +000097 nextToken();
98 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +000099 break;
100 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000101 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000102 addUnwrappedLine();
103 break;
104 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000105 if (HasOpeningBrace) {
106 return false;
107 } else {
108 // Stray '}' is an error.
109 Error = true;
110 nextToken();
111 addUnwrappedLine();
112 }
113 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000114 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000115 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000116 break;
117 }
118 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000119 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000120}
121
Alexander Kornienko15757312012-12-06 18:03:27 +0000122bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000123 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000124 nextToken();
125
Daniel Jasperbac016b2012-12-03 18:12:45 +0000126 addUnwrappedLine();
127
Alexander Kornienko15757312012-12-06 18:03:27 +0000128 Line.Level += AddLevels;
Manuel Klimeka5342db2013-01-06 20:07:31 +0000129 parseLevel(/*HasOpeningBrace=*/true);
Alexander Kornienko15757312012-12-06 18:03:27 +0000130 Line.Level -= AddLevels;
131
Alexander Kornienko393b0082012-12-04 15:40:36 +0000132 if (!FormatTok.Tok.is(tok::r_brace))
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000133 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000134
Manuel Klimekde768542013-01-07 18:10:23 +0000135 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000136 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000137}
138
139void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000140 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimekd4397b92013-01-04 23:34:14 +0000141 ScopedMacroState MacroState(Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000142 nextToken();
143
Manuel Klimeka080a182013-01-02 16:30:12 +0000144 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
145 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000146 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000147 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000148
Manuel Klimekd4397b92013-01-04 23:34:14 +0000149 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
150 case tok::pp_define:
151 parsePPDefine();
152 break;
153 default:
154 parsePPUnknown();
155 break;
156 }
157}
158
159void UnwrappedLineParser::parsePPDefine() {
160 nextToken();
161
162 if (FormatTok.Tok.getKind() != tok::identifier) {
163 parsePPUnknown();
164 return;
165 }
166 nextToken();
167 if (FormatTok.Tok.getKind() == tok::l_paren) {
168 parseParens();
169 }
170 addUnwrappedLine();
171 Line.Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000172
173 // Errors during a preprocessor directive can only affect the layout of the
174 // preprocessor directive, and thus we ignore them. An alternative approach
175 // would be to use the same approach we use on the file level (no
176 // re-indentation if there was a structural error) within the macro
177 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000178 parseFile();
179}
180
181void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000182 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000183 nextToken();
184 } while (!eof());
185 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000186}
187
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000188void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000189 // Consume leading line comments, e.g. for branches without compounds.
190 while (FormatTok.Tok.is(tok::comment)) {
191 nextToken();
192 addUnwrappedLine();
193 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000194}
195
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000196void UnwrappedLineParser::parseStructuralElement() {
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000197 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000198
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000199 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000200 switch (FormatTok.Tok.getKind()) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000201 case tok::kw_namespace:
202 parseNamespace();
203 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000204 case tok::kw_inline:
205 nextToken();
206 TokenNumber++;
207 if (FormatTok.Tok.is(tok::kw_namespace)) {
208 parseNamespace();
209 return;
210 }
211 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000212 case tok::kw_public:
213 case tok::kw_protected:
214 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000215 parseAccessSpecifier();
216 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000217 case tok::kw_if:
218 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000219 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000220 case tok::kw_for:
221 case tok::kw_while:
222 parseForOrWhileLoop();
223 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000224 case tok::kw_do:
225 parseDoWhile();
226 return;
227 case tok::kw_switch:
228 parseSwitch();
229 return;
230 case tok::kw_default:
231 nextToken();
232 parseLabel();
233 return;
234 case tok::kw_case:
235 parseCaseLabel();
236 return;
237 default:
238 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000239 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000240 do {
241 ++TokenNumber;
242 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000243 case tok::kw_enum:
244 parseEnum();
245 return;
Manuel Klimekde768542013-01-07 18:10:23 +0000246 case tok::kw_struct: // fallthrough
247 case tok::kw_class:
248 parseStructOrClass();
249 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000250 case tok::semi:
251 nextToken();
252 addUnwrappedLine();
253 return;
254 case tok::l_paren:
255 parseParens();
256 break;
257 case tok::l_brace:
258 parseBlock();
259 addUnwrappedLine();
260 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000261 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000262 nextToken();
263 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
264 parseLabel();
265 return;
266 }
267 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000268 case tok::equal:
269 nextToken();
270 // Skip initializers as they will be formatted by a later step.
271 if (FormatTok.Tok.is(tok::l_brace))
272 nextToken();
273 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000274 default:
275 nextToken();
276 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000277 }
278 } while (!eof());
279}
280
281void UnwrappedLineParser::parseParens() {
282 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
283 nextToken();
284 do {
285 switch (FormatTok.Tok.getKind()) {
286 case tok::l_paren:
287 parseParens();
288 break;
289 case tok::r_paren:
290 nextToken();
291 return;
292 default:
293 nextToken();
294 break;
295 }
296 } while (!eof());
297}
298
299void UnwrappedLineParser::parseIfThenElse() {
300 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
301 nextToken();
302 parseParens();
303 bool NeedsUnwrappedLine = false;
304 if (FormatTok.Tok.is(tok::l_brace)) {
305 parseBlock();
306 NeedsUnwrappedLine = true;
307 } else {
308 addUnwrappedLine();
309 ++Line.Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000310 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000311 --Line.Level;
312 }
313 if (FormatTok.Tok.is(tok::kw_else)) {
314 nextToken();
315 if (FormatTok.Tok.is(tok::l_brace)) {
316 parseBlock();
317 addUnwrappedLine();
318 } else if (FormatTok.Tok.is(tok::kw_if)) {
319 parseIfThenElse();
320 } else {
321 addUnwrappedLine();
322 ++Line.Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000323 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000324 --Line.Level;
325 }
326 } else if (NeedsUnwrappedLine) {
327 addUnwrappedLine();
328 }
329}
330
Alexander Kornienko15757312012-12-06 18:03:27 +0000331void UnwrappedLineParser::parseNamespace() {
332 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
333 nextToken();
334 if (FormatTok.Tok.is(tok::identifier))
335 nextToken();
336 if (FormatTok.Tok.is(tok::l_brace)) {
337 parseBlock(0);
338 addUnwrappedLine();
339 }
340 // FIXME: Add error handling.
341}
342
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000343void UnwrappedLineParser::parseForOrWhileLoop() {
344 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
345 "'for' or 'while' expected");
346 nextToken();
347 parseParens();
348 if (FormatTok.Tok.is(tok::l_brace)) {
349 parseBlock();
350 addUnwrappedLine();
351 } else {
352 addUnwrappedLine();
353 ++Line.Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000354 parseStructuralElement();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000355 --Line.Level;
356 }
357}
358
Daniel Jasperbac016b2012-12-03 18:12:45 +0000359void UnwrappedLineParser::parseDoWhile() {
360 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
361 nextToken();
362 if (FormatTok.Tok.is(tok::l_brace)) {
363 parseBlock();
364 } else {
365 addUnwrappedLine();
366 ++Line.Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000367 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000368 --Line.Level;
369 }
370
Alexander Kornienko393b0082012-12-04 15:40:36 +0000371 // FIXME: Add error handling.
372 if (!FormatTok.Tok.is(tok::kw_while)) {
373 addUnwrappedLine();
374 return;
375 }
376
Daniel Jasperbac016b2012-12-03 18:12:45 +0000377 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000378 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000379}
380
381void UnwrappedLineParser::parseLabel() {
382 // FIXME: remove all asserts.
383 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
384 nextToken();
385 unsigned OldLineLevel = Line.Level;
386 if (Line.Level > 0)
387 --Line.Level;
388 if (FormatTok.Tok.is(tok::l_brace)) {
389 parseBlock();
390 }
391 addUnwrappedLine();
392 Line.Level = OldLineLevel;
393}
394
395void UnwrappedLineParser::parseCaseLabel() {
396 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
397 // FIXME: fix handling of complex expressions here.
398 do {
399 nextToken();
400 } while (!eof() && !FormatTok.Tok.is(tok::colon));
401 parseLabel();
402}
403
404void UnwrappedLineParser::parseSwitch() {
405 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
406 nextToken();
407 parseParens();
408 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000409 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000410 addUnwrappedLine();
411 } else {
412 addUnwrappedLine();
Alexander Kornienko15757312012-12-06 18:03:27 +0000413 Line.Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000414 parseStructuralElement();
Alexander Kornienko15757312012-12-06 18:03:27 +0000415 Line.Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000416 }
417}
418
419void UnwrappedLineParser::parseAccessSpecifier() {
420 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000421 // Otherwise, we don't know what it is, and we'd better keep the next token.
422 if (FormatTok.Tok.is(tok::colon))
423 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000424 addUnwrappedLine();
425}
426
427void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000428 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000429 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000430 switch (FormatTok.Tok.getKind()) {
431 case tok::l_brace:
432 nextToken();
433 addUnwrappedLine();
434 ++Line.Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000435 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000436 break;
437 case tok::l_paren:
438 parseParens();
439 break;
440 case tok::comma:
441 nextToken();
442 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000443 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000444 break;
445 case tok::r_brace:
446 if (HasContents)
447 addUnwrappedLine();
448 --Line.Level;
449 nextToken();
450 break;
451 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000452 nextToken();
453 addUnwrappedLine();
454 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000455 default:
456 HasContents = true;
457 nextToken();
458 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000459 }
460 } while (!eof());
461}
462
Manuel Klimekde768542013-01-07 18:10:23 +0000463void UnwrappedLineParser::parseStructOrClass() {
464 nextToken();
465 do {
466 switch (FormatTok.Tok.getKind()) {
467 case tok::l_brace:
468 // FIXME: Think about how to resolve the error handling here.
469 parseBlock();
470 parseStructuralElement();
471 return;
472 case tok::semi:
473 nextToken();
474 addUnwrappedLine();
475 return;
476 default:
477 nextToken();
478 break;
479 }
480 } while (!eof());
481}
482
Daniel Jasperbac016b2012-12-03 18:12:45 +0000483void UnwrappedLineParser::addUnwrappedLine() {
484 // Consume trailing comments.
485 while (!eof() && FormatTok.NewlinesBefore == 0 &&
486 FormatTok.Tok.is(tok::comment)) {
487 nextToken();
488 }
Alexander Kornienko720ffb62012-12-05 13:56:52 +0000489 Callback.consumeUnwrappedLine(Line);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000490 Line.Tokens.clear();
491}
492
493bool UnwrappedLineParser::eof() const {
494 return FormatTok.Tok.is(tok::eof);
495}
496
497void UnwrappedLineParser::nextToken() {
498 if (eof())
499 return;
500 Line.Tokens.push_back(FormatTok);
Manuel Klimekd4397b92013-01-04 23:34:14 +0000501 readToken();
502}
503
504void UnwrappedLineParser::readToken() {
505 FormatTok = Tokens->getNextToken();
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000506 while (!Line.InPPDirective && FormatTok.Tok.is(tok::hash) &&
507 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
508 FormatTok.IsFirst)) {
Manuel Klimekd4397b92013-01-04 23:34:14 +0000509 // FIXME: This is incorrect - the correct way is to create a
510 // data structure that will construct the parts around the preprocessor
511 // directive as a structured \c UnwrappedLine.
512 addUnwrappedLine();
513 parsePPDirective();
514 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000515}
516
Daniel Jaspercd162382013-01-07 13:26:07 +0000517} // end namespace format
518} // end namespace clang