blob: 905758993e1f375c9d47b3ef91d583298f51fe2c [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)
Daniel Jasper26f7e782013-01-08 14:56:18 +000077 : RootTokenInitialized(false), Style(Style), Tokens(&Tokens),
78 Callback(Callback) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000079}
80
Alexander Kornienkocff563c2012-12-04 17:27:50 +000081bool UnwrappedLineParser::parse() {
Manuel Klimekd4397b92013-01-04 23:34:14 +000082 readToken();
83 return parseFile();
84}
85
86bool UnwrappedLineParser::parseFile() {
Manuel Klimeka5342db2013-01-06 20:07:31 +000087 bool Error = parseLevel(/*HasOpeningBrace=*/false);
Manuel Klimekd4397b92013-01-04 23:34:14 +000088 // Make sure to format the remaining tokens.
89 addUnwrappedLine();
90 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +000091}
92
Manuel Klimeka5342db2013-01-06 20:07:31 +000093bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
Alexander Kornienkocff563c2012-12-04 17:27:50 +000094 bool Error = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +000095 do {
96 switch (FormatTok.Tok.getKind()) {
Daniel Jasperbac016b2012-12-03 18:12:45 +000097 case tok::comment:
Daniel Jasper05b1ac82012-12-17 11:29:41 +000098 nextToken();
99 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000100 break;
101 case tok::l_brace:
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000102 Error |= parseBlock();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000103 addUnwrappedLine();
104 break;
105 case tok::r_brace:
Manuel Klimeka5342db2013-01-06 20:07:31 +0000106 if (HasOpeningBrace) {
107 return false;
108 } else {
109 // Stray '}' is an error.
110 Error = true;
111 nextToken();
112 addUnwrappedLine();
113 }
114 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000115 default:
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000116 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000117 break;
118 }
119 } while (!eof());
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000120 return Error;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000121}
122
Alexander Kornienko15757312012-12-06 18:03:27 +0000123bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
Alexander Kornienkoa3a2b3a2012-12-06 17:49:17 +0000124 assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
Daniel Jasperbac016b2012-12-03 18:12:45 +0000125 nextToken();
126
Daniel Jasperbac016b2012-12-03 18:12:45 +0000127 addUnwrappedLine();
128
Alexander Kornienko15757312012-12-06 18:03:27 +0000129 Line.Level += AddLevels;
Manuel Klimeka5342db2013-01-06 20:07:31 +0000130 parseLevel(/*HasOpeningBrace=*/true);
Alexander Kornienko15757312012-12-06 18:03:27 +0000131 Line.Level -= AddLevels;
132
Alexander Kornienko393b0082012-12-04 15:40:36 +0000133 if (!FormatTok.Tok.is(tok::r_brace))
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000134 return true;
Alexander Kornienko393b0082012-12-04 15:40:36 +0000135
Manuel Klimekde768542013-01-07 18:10:23 +0000136 nextToken(); // Munch the closing brace.
Alexander Kornienkocff563c2012-12-04 17:27:50 +0000137 return false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000138}
139
140void UnwrappedLineParser::parsePPDirective() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000141 assert(FormatTok.Tok.is(tok::hash) && "'#' expected");
Manuel Klimekd4397b92013-01-04 23:34:14 +0000142 ScopedMacroState MacroState(Line, Tokens, FormatTok);
Manuel Klimeka080a182013-01-02 16:30:12 +0000143 nextToken();
144
Manuel Klimeka080a182013-01-02 16:30:12 +0000145 if (FormatTok.Tok.getIdentifierInfo() == NULL) {
146 addUnwrappedLine();
Manuel Klimeka080a182013-01-02 16:30:12 +0000147 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000148 }
Manuel Klimeka080a182013-01-02 16:30:12 +0000149
Manuel Klimekd4397b92013-01-04 23:34:14 +0000150 switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) {
151 case tok::pp_define:
152 parsePPDefine();
153 break;
154 default:
155 parsePPUnknown();
156 break;
157 }
158}
159
160void UnwrappedLineParser::parsePPDefine() {
161 nextToken();
162
163 if (FormatTok.Tok.getKind() != tok::identifier) {
164 parsePPUnknown();
165 return;
166 }
167 nextToken();
168 if (FormatTok.Tok.getKind() == tok::l_paren) {
169 parseParens();
170 }
171 addUnwrappedLine();
172 Line.Level = 1;
Manuel Klimekc3d0c822013-01-07 09:34:28 +0000173
174 // Errors during a preprocessor directive can only affect the layout of the
175 // preprocessor directive, and thus we ignore them. An alternative approach
176 // would be to use the same approach we use on the file level (no
177 // re-indentation if there was a structural error) within the macro
178 // definition.
Manuel Klimekd4397b92013-01-04 23:34:14 +0000179 parseFile();
180}
181
182void UnwrappedLineParser::parsePPUnknown() {
Manuel Klimeka080a182013-01-02 16:30:12 +0000183 do {
Manuel Klimeka080a182013-01-02 16:30:12 +0000184 nextToken();
185 } while (!eof());
186 addUnwrappedLine();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000187}
188
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000189void UnwrappedLineParser::parseComments() {
Daniel Jasper33182dd2012-12-05 14:57:28 +0000190 // Consume leading line comments, e.g. for branches without compounds.
191 while (FormatTok.Tok.is(tok::comment)) {
192 nextToken();
193 addUnwrappedLine();
194 }
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000195}
196
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000197void UnwrappedLineParser::parseStructuralElement() {
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000198 parseComments();
Daniel Jasper33182dd2012-12-05 14:57:28 +0000199
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000200 int TokenNumber = 0;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000201 switch (FormatTok.Tok.getKind()) {
Nico Weber6092d4e2013-01-07 19:05:19 +0000202 case tok::at:
203 nextToken();
204 switch (FormatTok.Tok.getObjCKeywordID()) {
205 case tok::objc_public:
206 case tok::objc_protected:
207 case tok::objc_package:
208 case tok::objc_private:
209 return parseAccessSpecifier();
210 default:
211 break;
212 }
213 break;
Alexander Kornienko15757312012-12-06 18:03:27 +0000214 case tok::kw_namespace:
215 parseNamespace();
216 return;
Dmitri Gribenko1f94f2b2012-12-30 21:27:25 +0000217 case tok::kw_inline:
218 nextToken();
219 TokenNumber++;
220 if (FormatTok.Tok.is(tok::kw_namespace)) {
221 parseNamespace();
222 return;
223 }
224 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000225 case tok::kw_public:
226 case tok::kw_protected:
227 case tok::kw_private:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000228 parseAccessSpecifier();
229 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000230 case tok::kw_if:
231 parseIfThenElse();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000232 return;
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000233 case tok::kw_for:
234 case tok::kw_while:
235 parseForOrWhileLoop();
236 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000237 case tok::kw_do:
238 parseDoWhile();
239 return;
240 case tok::kw_switch:
241 parseSwitch();
242 return;
243 case tok::kw_default:
244 nextToken();
245 parseLabel();
246 return;
247 case tok::kw_case:
248 parseCaseLabel();
249 return;
250 default:
251 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000252 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000253 do {
254 ++TokenNumber;
255 switch (FormatTok.Tok.getKind()) {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000256 case tok::kw_enum:
257 parseEnum();
258 return;
Manuel Klimekde768542013-01-07 18:10:23 +0000259 case tok::kw_struct: // fallthrough
260 case tok::kw_class:
261 parseStructOrClass();
262 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000263 case tok::semi:
264 nextToken();
265 addUnwrappedLine();
266 return;
267 case tok::l_paren:
268 parseParens();
269 break;
270 case tok::l_brace:
271 parseBlock();
272 addUnwrappedLine();
273 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000274 case tok::identifier:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000275 nextToken();
276 if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) {
277 parseLabel();
278 return;
279 }
280 break;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000281 case tok::equal:
282 nextToken();
283 // Skip initializers as they will be formatted by a later step.
284 if (FormatTok.Tok.is(tok::l_brace))
285 nextToken();
286 break;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000287 default:
288 nextToken();
289 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000290 }
291 } while (!eof());
292}
293
294void UnwrappedLineParser::parseParens() {
295 assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
296 nextToken();
297 do {
298 switch (FormatTok.Tok.getKind()) {
299 case tok::l_paren:
300 parseParens();
301 break;
302 case tok::r_paren:
303 nextToken();
304 return;
305 default:
306 nextToken();
307 break;
308 }
309 } while (!eof());
310}
311
312void UnwrappedLineParser::parseIfThenElse() {
313 assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected");
314 nextToken();
315 parseParens();
316 bool NeedsUnwrappedLine = false;
317 if (FormatTok.Tok.is(tok::l_brace)) {
318 parseBlock();
319 NeedsUnwrappedLine = true;
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 if (FormatTok.Tok.is(tok::kw_else)) {
327 nextToken();
328 if (FormatTok.Tok.is(tok::l_brace)) {
329 parseBlock();
330 addUnwrappedLine();
331 } else if (FormatTok.Tok.is(tok::kw_if)) {
332 parseIfThenElse();
333 } else {
334 addUnwrappedLine();
335 ++Line.Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000336 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000337 --Line.Level;
338 }
339 } else if (NeedsUnwrappedLine) {
340 addUnwrappedLine();
341 }
342}
343
Alexander Kornienko15757312012-12-06 18:03:27 +0000344void UnwrappedLineParser::parseNamespace() {
345 assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected");
346 nextToken();
347 if (FormatTok.Tok.is(tok::identifier))
348 nextToken();
349 if (FormatTok.Tok.is(tok::l_brace)) {
350 parseBlock(0);
351 addUnwrappedLine();
352 }
353 // FIXME: Add error handling.
354}
355
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000356void UnwrappedLineParser::parseForOrWhileLoop() {
357 assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) &&
358 "'for' or 'while' expected");
359 nextToken();
360 parseParens();
361 if (FormatTok.Tok.is(tok::l_brace)) {
362 parseBlock();
363 addUnwrappedLine();
364 } else {
365 addUnwrappedLine();
366 ++Line.Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000367 parseStructuralElement();
Alexander Kornienko2e97cfc2012-12-05 15:06:06 +0000368 --Line.Level;
369 }
370}
371
Daniel Jasperbac016b2012-12-03 18:12:45 +0000372void UnwrappedLineParser::parseDoWhile() {
373 assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
374 nextToken();
375 if (FormatTok.Tok.is(tok::l_brace)) {
376 parseBlock();
377 } else {
378 addUnwrappedLine();
379 ++Line.Level;
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000380 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000381 --Line.Level;
382 }
383
Alexander Kornienko393b0082012-12-04 15:40:36 +0000384 // FIXME: Add error handling.
385 if (!FormatTok.Tok.is(tok::kw_while)) {
386 addUnwrappedLine();
387 return;
388 }
389
Daniel Jasperbac016b2012-12-03 18:12:45 +0000390 nextToken();
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000391 parseStructuralElement();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000392}
393
394void UnwrappedLineParser::parseLabel() {
395 // FIXME: remove all asserts.
396 assert(FormatTok.Tok.is(tok::colon) && "':' expected");
397 nextToken();
398 unsigned OldLineLevel = Line.Level;
399 if (Line.Level > 0)
400 --Line.Level;
401 if (FormatTok.Tok.is(tok::l_brace)) {
402 parseBlock();
403 }
404 addUnwrappedLine();
405 Line.Level = OldLineLevel;
406}
407
408void UnwrappedLineParser::parseCaseLabel() {
409 assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected");
410 // FIXME: fix handling of complex expressions here.
411 do {
412 nextToken();
413 } while (!eof() && !FormatTok.Tok.is(tok::colon));
414 parseLabel();
415}
416
417void UnwrappedLineParser::parseSwitch() {
418 assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected");
419 nextToken();
420 parseParens();
421 if (FormatTok.Tok.is(tok::l_brace)) {
Alexander Kornienko15757312012-12-06 18:03:27 +0000422 parseBlock(Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000423 addUnwrappedLine();
424 } else {
425 addUnwrappedLine();
Alexander Kornienko15757312012-12-06 18:03:27 +0000426 Line.Level += (Style.IndentCaseLabels ? 2 : 1);
Manuel Klimekf0ab0a32013-01-07 14:56:16 +0000427 parseStructuralElement();
Alexander Kornienko15757312012-12-06 18:03:27 +0000428 Line.Level -= (Style.IndentCaseLabels ? 2 : 1);
Daniel Jasperbac016b2012-12-03 18:12:45 +0000429 }
430}
431
432void UnwrappedLineParser::parseAccessSpecifier() {
433 nextToken();
Alexander Kornienko56e49c52012-12-10 16:34:48 +0000434 // Otherwise, we don't know what it is, and we'd better keep the next token.
435 if (FormatTok.Tok.is(tok::colon))
436 nextToken();
Daniel Jasperbac016b2012-12-03 18:12:45 +0000437 addUnwrappedLine();
438}
439
440void UnwrappedLineParser::parseEnum() {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000441 bool HasContents = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000442 do {
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000443 switch (FormatTok.Tok.getKind()) {
444 case tok::l_brace:
445 nextToken();
446 addUnwrappedLine();
447 ++Line.Level;
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000448 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000449 break;
450 case tok::l_paren:
451 parseParens();
452 break;
453 case tok::comma:
454 nextToken();
455 addUnwrappedLine();
Daniel Jasper05b1ac82012-12-17 11:29:41 +0000456 parseComments();
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000457 break;
458 case tok::r_brace:
459 if (HasContents)
460 addUnwrappedLine();
461 --Line.Level;
462 nextToken();
463 break;
464 case tok::semi:
Daniel Jasperbac016b2012-12-03 18:12:45 +0000465 nextToken();
466 addUnwrappedLine();
467 return;
Alexander Kornienkoa166e732012-12-04 14:46:19 +0000468 default:
469 HasContents = true;
470 nextToken();
471 break;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000472 }
473 } while (!eof());
474}
475
Manuel Klimekde768542013-01-07 18:10:23 +0000476void UnwrappedLineParser::parseStructOrClass() {
477 nextToken();
478 do {
479 switch (FormatTok.Tok.getKind()) {
480 case tok::l_brace:
481 // FIXME: Think about how to resolve the error handling here.
482 parseBlock();
483 parseStructuralElement();
484 return;
485 case tok::semi:
486 nextToken();
487 addUnwrappedLine();
488 return;
489 default:
490 nextToken();
491 break;
492 }
493 } while (!eof());
494}
495
Daniel Jasperbac016b2012-12-03 18:12:45 +0000496void UnwrappedLineParser::addUnwrappedLine() {
Daniel Jasper26f7e782013-01-08 14:56:18 +0000497 if (!RootTokenInitialized)
498 return;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000499 // Consume trailing comments.
500 while (!eof() && FormatTok.NewlinesBefore == 0 &&
501 FormatTok.Tok.is(tok::comment)) {
502 nextToken();
503 }
Alexander Kornienko720ffb62012-12-05 13:56:52 +0000504 Callback.consumeUnwrappedLine(Line);
Daniel Jasper26f7e782013-01-08 14:56:18 +0000505 RootTokenInitialized = false;
Daniel Jasperbac016b2012-12-03 18:12:45 +0000506}
507
508bool UnwrappedLineParser::eof() const {
509 return FormatTok.Tok.is(tok::eof);
510}
511
512void UnwrappedLineParser::nextToken() {
513 if (eof())
514 return;
Daniel Jasper26f7e782013-01-08 14:56:18 +0000515 if (RootTokenInitialized) {
516 LastInCurrentLine->Children.push_back(FormatTok);
517 LastInCurrentLine = &LastInCurrentLine->Children.back();
518 } else {
519 Line.RootToken = FormatTok;
520 RootTokenInitialized = true;
521 LastInCurrentLine = &Line.RootToken;
522 }
Manuel Klimekd4397b92013-01-04 23:34:14 +0000523 readToken();
524}
525
526void UnwrappedLineParser::readToken() {
527 FormatTok = Tokens->getNextToken();
Manuel Klimekf6fd00b2013-01-05 22:56:06 +0000528 while (!Line.InPPDirective && FormatTok.Tok.is(tok::hash) &&
529 ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
530 FormatTok.IsFirst)) {
Manuel Klimekd4397b92013-01-04 23:34:14 +0000531 // FIXME: This is incorrect - the correct way is to create a
532 // data structure that will construct the parts around the preprocessor
533 // directive as a structured \c UnwrappedLine.
534 addUnwrappedLine();
535 parsePPDirective();
536 }
Daniel Jasperbac016b2012-12-03 18:12:45 +0000537}
538
Daniel Jaspercd162382013-01-07 13:26:07 +0000539} // end namespace format
540} // end namespace clang