blob: 6c035b001c78a995ef786c863a27cd48ff8aae66 [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
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000103 switch (FormatTok.Tok.getKind()) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000104 case tok::kw_namespace:
105 parseNamespace();
106 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000107 case tok::kw_public:
108 case tok::kw_protected:
109 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000110 parseAccessSpecifier();
111 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000112 case tok::kw_if:
113 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000114 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000115 case tok::kw_for:
116 case tok::kw_while:
117 parseForOrWhileLoop();
118 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000119 case tok::kw_do:
120 parseDoWhile();
121 return;
122 case tok::kw_switch:
123 parseSwitch();
124 return;
125 case tok::kw_default:
126 nextToken();
127 parseLabel();
128 return;
129 case tok::kw_case:
130 parseCaseLabel();
131 return;
132 default:
133 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000134 }
135 int TokenNumber = 0;
136 do {
137 ++TokenNumber;
138 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000139 case tok::kw_enum:
140 parseEnum();
141 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000142 case tok::semi:
143 nextToken();
144 addUnwrappedLine();
145 return;
146 case tok::l_paren:
147 parseParens();
148 break;
149 case tok::l_brace:
150 parseBlock();
151 addUnwrappedLine();
152 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000153 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000154 nextToken();
155 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
156 parseLabel();
157 return;
158 }
159 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000160 case tok::equal:
161 nextToken();
162 // Skip initializers as they will be formatted by a later step.
163 if (FormatTok.Tok.is(tok::l_brace))
164 nextToken();
165 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000166 default:
167 nextToken();
168 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000169 }
170 } while (!eof());
171}
172
173void UnwrappedLineParser::parseParens() {
174 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
175 nextToken();
176 do {
177 switch (FormatTok.Tok.getKind()) {
178 case tok::l_paren:
179 parseParens();
180 break;
181 case tok::r_paren:
182 nextToken();
183 return;
184 default:
185 nextToken();
186 break;
187 }
188 } while (!eof());
189}
190
191void UnwrappedLineParser::parseIfThenElse() {
192 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
193 nextToken();
194 parseParens();
195 bool NeedsUnwrappedLine = false;
196 if (FormatTok.Tok.is(tok::l_brace)) {
197 parseBlock();
198 NeedsUnwrappedLine = true;
199 } else {
200 addUnwrappedLine();
201 ++Line.Level;
202 parseStatement();
203 --Line.Level;
204 }
205 if (FormatTok.Tok.is(tok::kw_else)) {
206 nextToken();
207 if (FormatTok.Tok.is(tok::l_brace)) {
208 parseBlock();
209 addUnwrappedLine();
210 } else if (FormatTok.Tok.is(tok::kw_if)) {
211 parseIfThenElse();
212 } else {
213 addUnwrappedLine();
214 ++Line.Level;
215 parseStatement();
216 --Line.Level;
217 }
218 } else if (NeedsUnwrappedLine) {
219 addUnwrappedLine();
220 }
221}
222
Alexander Kornienko15757312012-12-06 18:03:27 +0000223void UnwrappedLineParser::parseNamespace() {
224 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
225 nextToken();
226 if (FormatTok.Tok.is(tok::identifier))
227 nextToken();
228 if (FormatTok.Tok.is(tok::l_brace)) {
229 parseBlock(0);
230 addUnwrappedLine();
231 }
232 // FIXME: Add error handling.
233}
234
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000235void UnwrappedLineParser::parseForOrWhileLoop() {
236 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
237 "'for' or 'while' expected");
238 nextToken();
239 parseParens();
240 if (FormatTok.Tok.is(tok::l_brace)) {
241 parseBlock();
242 addUnwrappedLine();
243 } else {
244 addUnwrappedLine();
245 ++Line.Level;
246 parseStatement();
247 --Line.Level;
248 }
249}
250
Daniel Jasperbac016b2012-12-03 18:12:45 +0000251void UnwrappedLineParser::parseDoWhile() {
252 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
253 nextToken();
254 if (FormatTok.Tok.is(tok::l_brace)) {
255 parseBlock();
256 } else {
257 addUnwrappedLine();
258 ++Line.Level;
259 parseStatement();
260 --Line.Level;
261 }
262
Alexander Kornienko393b0082012-12-04 15:40:36 +0000263 // FIXME: Add error handling.
264 if (!FormatTok.Tok.is(tok::kw_while)) {
265 addUnwrappedLine();
266 return;
267 }
268
Daniel Jasperbac016b2012-12-03 18:12:45 +0000269 nextToken();
270 parseStatement();
271}
272
273void UnwrappedLineParser::parseLabel() {
274 // FIXME: remove all asserts.
275 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
276 nextToken();
277 unsigned OldLineLevel = Line.Level;
278 if (Line.Level > 0)
279 --Line.Level;
280 if (FormatTok.Tok.is(tok::l_brace)) {
281 parseBlock();
282 }
283 addUnwrappedLine();
284 Line.Level = OldLineLevel;
285}
286
287void UnwrappedLineParser::parseCaseLabel() {
288 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
289 // FIXME: fix handling of complex expressions here.
290 do {
291 nextToken();
292 } while (!eof() && !FormatTok.Tok.is(tok::colon));
293 parseLabel();
294}
295
296void UnwrappedLineParser::parseSwitch() {
297 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
298 nextToken();
299 parseParens();
300 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000301 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000302 addUnwrappedLine();
303 } else {
304 addUnwrappedLine();
Alexander Kornienko15757312012-12-06 18:03:27 +0000305 Line.Level += (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000306 parseStatement();
Alexander Kornienko15757312012-12-06 18:03:27 +0000307 Line.Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000308 }
309}
310
311void UnwrappedLineParser::parseAccessSpecifier() {
312 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000313 // Otherwise, we don't know what it is, and we'd better keep the next token.
314 if (FormatTok.Tok.is(tok::colon))
315 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000316 addUnwrappedLine();
317}
318
319void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000320 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000321 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000322 switch (FormatTok.Tok.getKind()) {
323 case tok::l_brace:
324 nextToken();
325 addUnwrappedLine();
326 ++Line.Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000327 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000328 break;
329 case tok::l_paren:
330 parseParens();
331 break;
332 case tok::comma:
333 nextToken();
334 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000335 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000336 break;
337 case tok::r_brace:
338 if (HasContents)
339 addUnwrappedLine();
340 --Line.Level;
341 nextToken();
342 break;
343 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000344 nextToken();
345 addUnwrappedLine();
346 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000347 default:
348 HasContents = true;
349 nextToken();
350 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000351 }
352 } while (!eof());
353}
354
355void UnwrappedLineParser::addUnwrappedLine() {
356 // Consume trailing comments.
357 while (!eof() && FormatTok.NewlinesBefore == 0 &&
358 FormatTok.Tok.is(tok::comment)) {
359 nextToken();
360 }
Alexander Kornienko720ffb62012-12-05 13:56:52 +0000361 Callback.consumeUnwrappedLine(Line);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000362 Line.Tokens.clear();
363}
364
365bool UnwrappedLineParser::eof() const {
366 return FormatTok.Tok.is(tok::eof);
367}
368
369void UnwrappedLineParser::nextToken() {
370 if (eof())
371 return;
372 Line.Tokens.push_back(FormatTok);
Alexander Kornienko469a21b2012-12-07 16:15:44 +0000373 FormatTok = Tokens.getNextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000374}
375
376} // end namespace format
377} // end namespace clang