blob: 7e91cb4351ff79cb52bf75655baa023a1e2140f6 [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)
Alexander Kornienko469a21b2012-12-07 16:15:44 +000028 : Style(Style),
29 Tokens(Tokens),
Daniel Jasperbac016b2012-12-03 18:12:45 +000030 Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000031}
32
Alexander Kornienkocff563c2012-12-04 17:27:50 +000033bool UnwrappedLineParser::parse() {
Alexander Kornienko469a21b2012-12-07 16:15:44 +000034 FormatTok = Tokens.getNextToken();
Alexander Kornienkocff563c2012-12-04 17:27:50 +000035 return parseLevel();
Daniel Jasperbac016b2012-12-03 18:12:45 +000036}
37
Alexander Kornienkocff563c2012-12-04 17:27:50 +000038bool UnwrappedLineParser::parseLevel() {
39 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +000040 do {
41 switch (FormatTok.Tok.getKind()) {
42 case tok::hash:
43 parsePPDirective();
44 break;
45 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +000046 nextToken();
47 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +000048 break;
49 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +000050 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +000051 addUnwrappedLine();
52 break;
53 case tok::r_brace:
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +000054 // Stray '}' is an error.
55 return true;
Daniel Jasperbac016b2012-12-03 18:12:45 +000056 default:
57 parseStatement();
58 break;
59 }
60 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +000061 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +000062}
63
Alexander Kornienko15757312012-12-06 18:03:27 +000064bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +000065 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +000066 nextToken();
67
Daniel Jasperbac016b2012-12-03 18:12:45 +000068 addUnwrappedLine();
69
Alexander Kornienko15757312012-12-06 18:03:27 +000070 Line.Level += AddLevels;
Daniel Jasperbac016b2012-12-03 18:12:45 +000071 parseLevel();
Alexander Kornienko15757312012-12-06 18:03:27 +000072 Line.Level -= AddLevels;
73
Alexander Kornienko393b0082012-12-04 15:40:36 +000074 // FIXME: Add error handling.
75 if (!FormatTok.Tok.is(tok::r_brace))
Alexander Kornienkocff563c2012-12-04 17:27:50 +000076 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +000077
Daniel Jasperbac016b2012-12-03 18:12:45 +000078 nextToken();
79 if (FormatTok.Tok.is(tok::semi))
80 nextToken();
Alexander Kornienkocff563c2012-12-04 17:27:50 +000081 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +000082}
83
84void UnwrappedLineParser::parsePPDirective() {
85 while (!eof()) {
86 nextToken();
87 if (FormatTok.NewlinesBefore > 0) {
88 addUnwrappedLine();
89 return;
90 }
91 }
92}
93
Daniel Jasper05b1ac82012-12-17 11:29:41 +000094void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +000095 // Consume leading line comments, e.g. for branches without compounds.
96 while (FormatTok.Tok.is(tok::comment)) {
97 nextToken();
98 addUnwrappedLine();
99 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000100}
101
102void UnwrappedLineParser::parseStatement() {
103 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000104
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000105 switch (FormatTok.Tok.getKind()) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000106 case tok::kw_namespace:
107 parseNamespace();
108 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000109 case tok::kw_public:
110 case tok::kw_protected:
111 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000112 parseAccessSpecifier();
113 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000114 case tok::kw_if:
115 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000116 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000117 case tok::kw_for:
118 case tok::kw_while:
119 parseForOrWhileLoop();
120 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000121 case tok::kw_do:
122 parseDoWhile();
123 return;
124 case tok::kw_switch:
125 parseSwitch();
126 return;
127 case tok::kw_default:
128 nextToken();
129 parseLabel();
130 return;
131 case tok::kw_case:
132 parseCaseLabel();
133 return;
134 default:
135 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000136 }
137 int TokenNumber = 0;
138 do {
139 ++TokenNumber;
140 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000141 case tok::kw_enum:
142 parseEnum();
143 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000144 case tok::semi:
145 nextToken();
146 addUnwrappedLine();
147 return;
148 case tok::l_paren:
149 parseParens();
150 break;
151 case tok::l_brace:
152 parseBlock();
153 addUnwrappedLine();
154 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000155 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000156 nextToken();
157 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
158 parseLabel();
159 return;
160 }
161 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000162 case tok::equal:
163 nextToken();
164 // Skip initializers as they will be formatted by a later step.
165 if (FormatTok.Tok.is(tok::l_brace))
166 nextToken();
167 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000168 default:
169 nextToken();
170 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000171 }
172 } while (!eof());
173}
174
175void UnwrappedLineParser::parseParens() {
176 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
177 nextToken();
178 do {
179 switch (FormatTok.Tok.getKind()) {
180 case tok::l_paren:
181 parseParens();
182 break;
183 case tok::r_paren:
184 nextToken();
185 return;
186 default:
187 nextToken();
188 break;
189 }
190 } while (!eof());
191}
192
193void UnwrappedLineParser::parseIfThenElse() {
194 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
195 nextToken();
196 parseParens();
197 bool NeedsUnwrappedLine = false;
198 if (FormatTok.Tok.is(tok::l_brace)) {
199 parseBlock();
200 NeedsUnwrappedLine = true;
201 } else {
202 addUnwrappedLine();
203 ++Line.Level;
204 parseStatement();
205 --Line.Level;
206 }
207 if (FormatTok.Tok.is(tok::kw_else)) {
208 nextToken();
209 if (FormatTok.Tok.is(tok::l_brace)) {
210 parseBlock();
211 addUnwrappedLine();
212 } else if (FormatTok.Tok.is(tok::kw_if)) {
213 parseIfThenElse();
214 } else {
215 addUnwrappedLine();
216 ++Line.Level;
217 parseStatement();
218 --Line.Level;
219 }
220 } else if (NeedsUnwrappedLine) {
221 addUnwrappedLine();
222 }
223}
224
Alexander Kornienko15757312012-12-06 18:03:27 +0000225void UnwrappedLineParser::parseNamespace() {
226 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
227 nextToken();
228 if (FormatTok.Tok.is(tok::identifier))
229 nextToken();
230 if (FormatTok.Tok.is(tok::l_brace)) {
231 parseBlock(0);
232 addUnwrappedLine();
233 }
234 // FIXME: Add error handling.
235}
236
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000237void UnwrappedLineParser::parseForOrWhileLoop() {
238 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
239 "'for' or 'while' expected");
240 nextToken();
241 parseParens();
242 if (FormatTok.Tok.is(tok::l_brace)) {
243 parseBlock();
244 addUnwrappedLine();
245 } else {
246 addUnwrappedLine();
247 ++Line.Level;
248 parseStatement();
249 --Line.Level;
250 }
251}
252
Daniel Jasperbac016b2012-12-03 18:12:45 +0000253void UnwrappedLineParser::parseDoWhile() {
254 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
255 nextToken();
256 if (FormatTok.Tok.is(tok::l_brace)) {
257 parseBlock();
258 } else {
259 addUnwrappedLine();
260 ++Line.Level;
261 parseStatement();
262 --Line.Level;
263 }
264
Alexander Kornienko393b0082012-12-04 15:40:36 +0000265 // FIXME: Add error handling.
266 if (!FormatTok.Tok.is(tok::kw_while)) {
267 addUnwrappedLine();
268 return;
269 }
270
Daniel Jasperbac016b2012-12-03 18:12:45 +0000271 nextToken();
272 parseStatement();
273}
274
275void UnwrappedLineParser::parseLabel() {
276 // FIXME: remove all asserts.
277 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
278 nextToken();
279 unsigned OldLineLevel = Line.Level;
280 if (Line.Level > 0)
281 --Line.Level;
282 if (FormatTok.Tok.is(tok::l_brace)) {
283 parseBlock();
284 }
285 addUnwrappedLine();
286 Line.Level = OldLineLevel;
287}
288
289void UnwrappedLineParser::parseCaseLabel() {
290 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
291 // FIXME: fix handling of complex expressions here.
292 do {
293 nextToken();
294 } while (!eof() && !FormatTok.Tok.is(tok::colon));
295 parseLabel();
296}
297
298void UnwrappedLineParser::parseSwitch() {
299 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
300 nextToken();
301 parseParens();
302 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000303 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000304 addUnwrappedLine();
305 } else {
306 addUnwrappedLine();
Alexander Kornienko15757312012-12-06 18:03:27 +0000307 Line.Level += (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000308 parseStatement();
Alexander Kornienko15757312012-12-06 18:03:27 +0000309 Line.Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000310 }
311}
312
313void UnwrappedLineParser::parseAccessSpecifier() {
314 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000315 // Otherwise, we don't know what it is, and we'd better keep the next token.
316 if (FormatTok.Tok.is(tok::colon))
317 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000318 addUnwrappedLine();
319}
320
321void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000322 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000323 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000324 switch (FormatTok.Tok.getKind()) {
325 case tok::l_brace:
326 nextToken();
327 addUnwrappedLine();
328 ++Line.Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000329 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000330 break;
331 case tok::l_paren:
332 parseParens();
333 break;
334 case tok::comma:
335 nextToken();
336 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000337 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000338 break;
339 case tok::r_brace:
340 if (HasContents)
341 addUnwrappedLine();
342 --Line.Level;
343 nextToken();
344 break;
345 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000346 nextToken();
347 addUnwrappedLine();
348 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000349 default:
350 HasContents = true;
351 nextToken();
352 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000353 }
354 } while (!eof());
355}
356
357void UnwrappedLineParser::addUnwrappedLine() {
358 // Consume trailing comments.
359 while (!eof() && FormatTok.NewlinesBefore == 0 &&
360 FormatTok.Tok.is(tok::comment)) {
361 nextToken();
362 }
Alexander Kornienko720ffb62012-12-05 13:56:52 +0000363 Callback.consumeUnwrappedLine(Line);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000364 Line.Tokens.clear();
365}
366
367bool UnwrappedLineParser::eof() const {
368 return FormatTok.Tok.is(tok::eof);
369}
370
371void UnwrappedLineParser::nextToken() {
372 if (eof())
373 return;
374 Line.Tokens.push_back(FormatTok);
Alexander Kornienko469a21b2012-12-07 16:15:44 +0000375 FormatTok = Tokens.getNextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000376}
377
378} // end namespace format
379} // end namespace clang