blob: 78a1abdcf8df5d4a027e3fdcfff08aa7f8e46e83 [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
Alexander Kornienko469a21b2012-12-07 16:15:44 +000025UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
26 FormatTokenSource &Tokens,
Daniel Jasperbac016b2012-12-03 18:12:45 +000027 UnwrappedLineConsumer &Callback)
Daniel Jasperd7610b82012-12-24 16:51:15 +000028 : Style(Style), Tokens(Tokens), Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000029}
30
Alexander Kornienkocff563c2012-12-04 17:27:50 +000031bool UnwrappedLineParser::parse() {
Alexander Kornienko469a21b2012-12-07 16:15:44 +000032 FormatTok = Tokens.getNextToken();
Alexander Kornienkocff563c2012-12-04 17:27:50 +000033 return parseLevel();
Daniel Jasperbac016b2012-12-03 18:12:45 +000034}
35
Alexander Kornienkocff563c2012-12-04 17:27:50 +000036bool UnwrappedLineParser::parseLevel() {
37 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +000038 do {
39 switch (FormatTok.Tok.getKind()) {
40 case tok::hash:
41 parsePPDirective();
42 break;
43 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +000044 nextToken();
45 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +000046 break;
47 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +000048 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +000049 addUnwrappedLine();
50 break;
51 case tok::r_brace:
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +000052 // Stray '}' is an error.
53 return true;
Daniel Jasperbac016b2012-12-03 18:12:45 +000054 default:
55 parseStatement();
56 break;
57 }
58 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +000059 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +000060}
61
Alexander Kornienko15757312012-12-06 18:03:27 +000062bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +000063 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +000064 nextToken();
65
Daniel Jasperbac016b2012-12-03 18:12:45 +000066 addUnwrappedLine();
67
Alexander Kornienko15757312012-12-06 18:03:27 +000068 Line.Level += AddLevels;
Daniel Jasperbac016b2012-12-03 18:12:45 +000069 parseLevel();
Alexander Kornienko15757312012-12-06 18:03:27 +000070 Line.Level -= AddLevels;
71
Alexander Kornienko393b0082012-12-04 15:40:36 +000072 // FIXME: Add error handling.
73 if (!FormatTok.Tok.is(tok::r_brace))
Alexander Kornienkocff563c2012-12-04 17:27:50 +000074 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +000075
Daniel Jasperbac016b2012-12-03 18:12:45 +000076 nextToken();
77 if (FormatTok.Tok.is(tok::semi))
78 nextToken();
Alexander Kornienkocff563c2012-12-04 17:27:50 +000079 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +000080}
81
82void UnwrappedLineParser::parsePPDirective() {
83 while (!eof()) {
84 nextToken();
85 if (FormatTok.NewlinesBefore > 0) {
86 addUnwrappedLine();
87 return;
88 }
89 }
90}
91
Daniel Jasper05b1ac82012-12-17 11:29:41 +000092void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +000093 // Consume leading line comments, e.g. for branches without compounds.
94 while (FormatTok.Tok.is(tok::comment)) {
95 nextToken();
96 addUnwrappedLine();
97 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +000098}
99
100void UnwrappedLineParser::parseStatement() {
101 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000102
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000103 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000104 switch (FormatTok.Tok.getKind()) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000105 case tok::kw_namespace:
106 parseNamespace();
107 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000108 case tok::kw_inline:
109 nextToken();
110 TokenNumber++;
111 if (FormatTok.Tok.is(tok::kw_namespace)) {
112 parseNamespace();
113 return;
114 }
115 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000116 case tok::kw_public:
117 case tok::kw_protected:
118 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000119 parseAccessSpecifier();
120 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000121 case tok::kw_if:
122 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000123 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000124 case tok::kw_for:
125 case tok::kw_while:
126 parseForOrWhileLoop();
127 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000128 case tok::kw_do:
129 parseDoWhile();
130 return;
131 case tok::kw_switch:
132 parseSwitch();
133 return;
134 case tok::kw_default:
135 nextToken();
136 parseLabel();
137 return;
138 case tok::kw_case:
139 parseCaseLabel();
140 return;
141 default:
142 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000143 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000144 do {
145 ++TokenNumber;
146 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000147 case tok::kw_enum:
148 parseEnum();
149 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000150 case tok::semi:
151 nextToken();
152 addUnwrappedLine();
153 return;
154 case tok::l_paren:
155 parseParens();
156 break;
157 case tok::l_brace:
158 parseBlock();
159 addUnwrappedLine();
160 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000161 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000162 nextToken();
163 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
164 parseLabel();
165 return;
166 }
167 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000168 case tok::equal:
169 nextToken();
170 // Skip initializers as they will be formatted by a later step.
171 if (FormatTok.Tok.is(tok::l_brace))
172 nextToken();
173 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000174 default:
175 nextToken();
176 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000177 }
178 } while (!eof());
179}
180
181void UnwrappedLineParser::parseParens() {
182 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
183 nextToken();
184 do {
185 switch (FormatTok.Tok.getKind()) {
186 case tok::l_paren:
187 parseParens();
188 break;
189 case tok::r_paren:
190 nextToken();
191 return;
192 default:
193 nextToken();
194 break;
195 }
196 } while (!eof());
197}
198
199void UnwrappedLineParser::parseIfThenElse() {
200 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
201 nextToken();
202 parseParens();
203 bool NeedsUnwrappedLine = false;
204 if (FormatTok.Tok.is(tok::l_brace)) {
205 parseBlock();
206 NeedsUnwrappedLine = true;
207 } else {
208 addUnwrappedLine();
209 ++Line.Level;
210 parseStatement();
211 --Line.Level;
212 }
213 if (FormatTok.Tok.is(tok::kw_else)) {
214 nextToken();
215 if (FormatTok.Tok.is(tok::l_brace)) {
216 parseBlock();
217 addUnwrappedLine();
218 } else if (FormatTok.Tok.is(tok::kw_if)) {
219 parseIfThenElse();
220 } else {
221 addUnwrappedLine();
222 ++Line.Level;
223 parseStatement();
224 --Line.Level;
225 }
226 } else if (NeedsUnwrappedLine) {
227 addUnwrappedLine();
228 }
229}
230
Alexander Kornienko15757312012-12-06 18:03:27 +0000231void UnwrappedLineParser::parseNamespace() {
232 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
233 nextToken();
234 if (FormatTok.Tok.is(tok::identifier))
235 nextToken();
236 if (FormatTok.Tok.is(tok::l_brace)) {
237 parseBlock(0);
238 addUnwrappedLine();
239 }
240 // FIXME: Add error handling.
241}
242
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000243void UnwrappedLineParser::parseForOrWhileLoop() {
244 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
245 "'for' or 'while' expected");
246 nextToken();
247 parseParens();
248 if (FormatTok.Tok.is(tok::l_brace)) {
249 parseBlock();
250 addUnwrappedLine();
251 } else {
252 addUnwrappedLine();
253 ++Line.Level;
254 parseStatement();
255 --Line.Level;
256 }
257}
258
Daniel Jasperbac016b2012-12-03 18:12:45 +0000259void UnwrappedLineParser::parseDoWhile() {
260 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
261 nextToken();
262 if (FormatTok.Tok.is(tok::l_brace)) {
263 parseBlock();
264 } else {
265 addUnwrappedLine();
266 ++Line.Level;
267 parseStatement();
268 --Line.Level;
269 }
270
Alexander Kornienko393b0082012-12-04 15:40:36 +0000271 // FIXME: Add error handling.
272 if (!FormatTok.Tok.is(tok::kw_while)) {
273 addUnwrappedLine();
274 return;
275 }
276
Daniel Jasperbac016b2012-12-03 18:12:45 +0000277 nextToken();
278 parseStatement();
279}
280
281void UnwrappedLineParser::parseLabel() {
282 // FIXME: remove all asserts.
283 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
284 nextToken();
285 unsigned OldLineLevel = Line.Level;
286 if (Line.Level > 0)
287 --Line.Level;
288 if (FormatTok.Tok.is(tok::l_brace)) {
289 parseBlock();
290 }
291 addUnwrappedLine();
292 Line.Level = OldLineLevel;
293}
294
295void UnwrappedLineParser::parseCaseLabel() {
296 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
297 // FIXME: fix handling of complex expressions here.
298 do {
299 nextToken();
300 } while (!eof() && !FormatTok.Tok.is(tok::colon));
301 parseLabel();
302}
303
304void UnwrappedLineParser::parseSwitch() {
305 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
306 nextToken();
307 parseParens();
308 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000309 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000310 addUnwrappedLine();
311 } else {
312 addUnwrappedLine();
Alexander Kornienko15757312012-12-06 18:03:27 +0000313 Line.Level += (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000314 parseStatement();
Alexander Kornienko15757312012-12-06 18:03:27 +0000315 Line.Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000316 }
317}
318
319void UnwrappedLineParser::parseAccessSpecifier() {
320 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000321 // Otherwise, we don't know what it is, and we'd better keep the next token.
322 if (FormatTok.Tok.is(tok::colon))
323 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000324 addUnwrappedLine();
325}
326
327void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000328 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000329 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000330 switch (FormatTok.Tok.getKind()) {
331 case tok::l_brace:
332 nextToken();
333 addUnwrappedLine();
334 ++Line.Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000335 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000336 break;
337 case tok::l_paren:
338 parseParens();
339 break;
340 case tok::comma:
341 nextToken();
342 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000343 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000344 break;
345 case tok::r_brace:
346 if (HasContents)
347 addUnwrappedLine();
348 --Line.Level;
349 nextToken();
350 break;
351 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000352 nextToken();
353 addUnwrappedLine();
354 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000355 default:
356 HasContents = true;
357 nextToken();
358 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000359 }
360 } while (!eof());
361}
362
363void UnwrappedLineParser::addUnwrappedLine() {
364 // Consume trailing comments.
365 while (!eof() && FormatTok.NewlinesBefore == 0 &&
366 FormatTok.Tok.is(tok::comment)) {
367 nextToken();
368 }
Alexander Kornienko720ffb62012-12-05 13:56:52 +0000369 Callback.consumeUnwrappedLine(Line);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000370 Line.Tokens.clear();
371}
372
373bool UnwrappedLineParser::eof() const {
374 return FormatTok.Tok.is(tok::eof);
375}
376
377void UnwrappedLineParser::nextToken() {
378 if (eof())
379 return;
380 Line.Tokens.push_back(FormatTok);
Alexander Kornienko469a21b2012-12-07 16:15:44 +0000381 FormatTok = Tokens.getNextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000382}
383
384} // end namespace format
385} // end namespace clang