| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 1 | //===--- 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 | /// | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 14 | //===----------------------------------------------------------------------===// | 
 | 15 |  | 
| Manuel Klimek | 8fa3799 | 2013-01-16 12:31:12 +0000 | [diff] [blame] | 16 | #define DEBUG_TYPE "format-parser" | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 17 |  | 
| Chandler Carruth | b1ba0ef | 2013-01-19 08:09:44 +0000 | [diff] [blame] | 18 | #include "UnwrappedLineParser.h" | 
| Manuel Klimek | 8fa3799 | 2013-01-16 12:31:12 +0000 | [diff] [blame] | 19 | #include "clang/Basic/Diagnostic.h" | 
 | 20 | #include "llvm/Support/Debug.h" | 
| Manuel Klimek | 8fa3799 | 2013-01-16 12:31:12 +0000 | [diff] [blame] | 21 |  | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 22 | namespace clang { | 
 | 23 | namespace format { | 
 | 24 |  | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 25 | class ScopedDeclarationState { | 
 | 26 | public: | 
 | 27 |   ScopedDeclarationState(UnwrappedLine &Line, std::vector<bool> &Stack, | 
 | 28 |                          bool MustBeDeclaration) | 
 | 29 |       : Line(Line), Stack(Stack) { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 30 |     Line.MustBeDeclaration = MustBeDeclaration; | 
| Manuel Klimek | 836b58f | 2013-01-23 11:03:04 +0000 | [diff] [blame] | 31 |     Stack.push_back(MustBeDeclaration); | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 32 |   } | 
 | 33 |   ~ScopedDeclarationState() { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 34 |     Stack.pop_back(); | 
| Manuel Klimek | a32a7fd | 2013-01-23 14:08:21 +0000 | [diff] [blame] | 35 |     if (!Stack.empty()) | 
 | 36 |       Line.MustBeDeclaration = Stack.back(); | 
 | 37 |     else | 
 | 38 |       Line.MustBeDeclaration = true; | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 39 |   } | 
 | 40 | private: | 
 | 41 |   UnwrappedLine &Line; | 
 | 42 |   std::vector<bool> &Stack; | 
 | 43 | }; | 
 | 44 |  | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 45 | class ScopedMacroState : public FormatTokenSource { | 
 | 46 | public: | 
 | 47 |   ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource, | 
 | 48 |                    FormatToken &ResetToken) | 
 | 49 |       : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken), | 
| Manuel Klimek | c37b4d6 | 2013-01-05 22:14:16 +0000 | [diff] [blame] | 50 |         PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource) { | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 51 |     TokenSource = this; | 
| Manuel Klimek | c37b4d6 | 2013-01-05 22:14:16 +0000 | [diff] [blame] | 52 |     Line.Level = 0; | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 53 |     Line.InPPDirective = true; | 
 | 54 |   } | 
 | 55 |  | 
 | 56 |   ~ScopedMacroState() { | 
 | 57 |     TokenSource = PreviousTokenSource; | 
 | 58 |     ResetToken = Token; | 
 | 59 |     Line.InPPDirective = false; | 
| Manuel Klimek | c37b4d6 | 2013-01-05 22:14:16 +0000 | [diff] [blame] | 60 |     Line.Level = PreviousLineLevel; | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 61 |   } | 
 | 62 |  | 
 | 63 |   virtual FormatToken getNextToken() { | 
| Manuel Klimek | dd5b101 | 2013-01-07 10:03:37 +0000 | [diff] [blame] | 64 |     // The \c UnwrappedLineParser guards against this by never calling | 
 | 65 |     // \c getNextToken() after it has encountered the first eof token. | 
 | 66 |     assert(!eof()); | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 67 |     Token = PreviousTokenSource->getNextToken(); | 
 | 68 |     if (eof()) | 
 | 69 |       return createEOF(); | 
 | 70 |     return Token; | 
 | 71 |   } | 
 | 72 |  | 
 | 73 | private: | 
 | 74 |   bool eof() { | 
 | 75 |     return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline; | 
 | 76 |   } | 
 | 77 |  | 
 | 78 |   FormatToken createEOF() { | 
 | 79 |     FormatToken FormatTok; | 
 | 80 |     FormatTok.Tok.startToken(); | 
 | 81 |     FormatTok.Tok.setKind(tok::eof); | 
 | 82 |     return FormatTok; | 
 | 83 |   } | 
 | 84 |  | 
 | 85 |   UnwrappedLine &Line; | 
 | 86 |   FormatTokenSource *&TokenSource; | 
 | 87 |   FormatToken &ResetToken; | 
| Manuel Klimek | c37b4d6 | 2013-01-05 22:14:16 +0000 | [diff] [blame] | 88 |   unsigned PreviousLineLevel; | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 89 |   FormatTokenSource *PreviousTokenSource; | 
 | 90 |  | 
 | 91 |   FormatToken Token; | 
 | 92 | }; | 
 | 93 |  | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 94 | class ScopedLineState { | 
 | 95 | public: | 
| Manuel Klimek | 525fe16 | 2013-01-18 14:04:34 +0000 | [diff] [blame] | 96 |   ScopedLineState(UnwrappedLineParser &Parser, | 
 | 97 |                   bool SwitchToPreprocessorLines = false) | 
 | 98 |       : Parser(Parser), SwitchToPreprocessorLines(SwitchToPreprocessorLines) { | 
 | 99 |     if (SwitchToPreprocessorLines) | 
 | 100 |       Parser.CurrentLines = &Parser.PreprocessorDirectives; | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 101 |     PreBlockLine = Parser.Line.take(); | 
| Daniel Jasper | cbb6c41 | 2013-01-16 09:10:19 +0000 | [diff] [blame] | 102 |     Parser.Line.reset(new UnwrappedLine()); | 
 | 103 |     Parser.Line->Level = PreBlockLine->Level; | 
 | 104 |     Parser.Line->InPPDirective = PreBlockLine->InPPDirective; | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 105 |   } | 
 | 106 |  | 
 | 107 |   ~ScopedLineState() { | 
| Daniel Jasper | cbb6c41 | 2013-01-16 09:10:19 +0000 | [diff] [blame] | 108 |     if (!Parser.Line->Tokens.empty()) { | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 109 |       Parser.addUnwrappedLine(); | 
 | 110 |     } | 
| Daniel Jasper | cbb6c41 | 2013-01-16 09:10:19 +0000 | [diff] [blame] | 111 |     assert(Parser.Line->Tokens.empty()); | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 112 |     Parser.Line.reset(PreBlockLine); | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 113 |     Parser.MustBreakBeforeNextToken = true; | 
| Manuel Klimek | 525fe16 | 2013-01-18 14:04:34 +0000 | [diff] [blame] | 114 |     if (SwitchToPreprocessorLines) | 
 | 115 |       Parser.CurrentLines = &Parser.Lines; | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 116 |   } | 
 | 117 |  | 
 | 118 | private: | 
 | 119 |   UnwrappedLineParser &Parser; | 
| Manuel Klimek | 525fe16 | 2013-01-18 14:04:34 +0000 | [diff] [blame] | 120 |   const bool SwitchToPreprocessorLines; | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 121 |  | 
 | 122 |   UnwrappedLine *PreBlockLine; | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 123 | }; | 
 | 124 |  | 
| Alexander Kornienko | 3048aea | 2013-01-10 15:05:09 +0000 | [diff] [blame] | 125 | UnwrappedLineParser::UnwrappedLineParser( | 
 | 126 |     clang::DiagnosticsEngine &Diag, const FormatStyle &Style, | 
 | 127 |     FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback) | 
| Manuel Klimek | 525fe16 | 2013-01-18 14:04:34 +0000 | [diff] [blame] | 128 |     : Line(new UnwrappedLine), MustBreakBeforeNextToken(false), | 
 | 129 |       CurrentLines(&Lines), Diag(Diag), Style(Style), Tokens(&Tokens), | 
 | 130 |       Callback(Callback) {} | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 131 |  | 
| Alexander Kornienko | cff563c | 2012-12-04 17:27:50 +0000 | [diff] [blame] | 132 | bool UnwrappedLineParser::parse() { | 
| Manuel Klimek | 8fa3799 | 2013-01-16 12:31:12 +0000 | [diff] [blame] | 133 |   DEBUG(llvm::dbgs() << "----\n"); | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 134 |   readToken(); | 
| Manuel Klimek | 525fe16 | 2013-01-18 14:04:34 +0000 | [diff] [blame] | 135 |   bool Error = parseFile(); | 
 | 136 |   for (std::vector<UnwrappedLine>::iterator I = Lines.begin(), | 
 | 137 |                                             E = Lines.end(); | 
 | 138 |        I != E; ++I) { | 
 | 139 |     Callback.consumeUnwrappedLine(*I); | 
 | 140 |   } | 
 | 141 |   return Error; | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 142 | } | 
 | 143 |  | 
 | 144 | bool UnwrappedLineParser::parseFile() { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 145 |   ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, | 
 | 146 |                                           /*MustBeDeclaration=*/ true); | 
| Manuel Klimek | a5342db | 2013-01-06 20:07:31 +0000 | [diff] [blame] | 147 |   bool Error = parseLevel(/*HasOpeningBrace=*/false); | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 148 |   // Make sure to format the remaining tokens. | 
| Manuel Klimek | 86721d2 | 2013-01-22 16:31:55 +0000 | [diff] [blame] | 149 |   flushComments(true); | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 150 |   addUnwrappedLine(); | 
 | 151 |   return Error; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 152 | } | 
 | 153 |  | 
| Manuel Klimek | a5342db | 2013-01-06 20:07:31 +0000 | [diff] [blame] | 154 | bool UnwrappedLineParser::parseLevel(bool HasOpeningBrace) { | 
| Alexander Kornienko | cff563c | 2012-12-04 17:27:50 +0000 | [diff] [blame] | 155 |   bool Error = false; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 156 |   do { | 
 | 157 |     switch (FormatTok.Tok.getKind()) { | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 158 |     case tok::comment: | 
| Daniel Jasper | 05b1ac8 | 2012-12-17 11:29:41 +0000 | [diff] [blame] | 159 |       nextToken(); | 
 | 160 |       addUnwrappedLine(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 161 |       break; | 
 | 162 |     case tok::l_brace: | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 163 |       // FIXME: Add parameter whether this can happen - if this happens, we must | 
 | 164 |       // be in a non-declaration context. | 
 | 165 |       Error |= parseBlock(/*MustBeDeclaration=*/ false); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 166 |       addUnwrappedLine(); | 
 | 167 |       break; | 
 | 168 |     case tok::r_brace: | 
| Manuel Klimek | a5342db | 2013-01-06 20:07:31 +0000 | [diff] [blame] | 169 |       if (HasOpeningBrace) { | 
 | 170 |         return false; | 
 | 171 |       } else { | 
| Alexander Kornienko | 3048aea | 2013-01-10 15:05:09 +0000 | [diff] [blame] | 172 |         Diag.Report(FormatTok.Tok.getLocation(), | 
 | 173 |                     Diag.getCustomDiagID(clang::DiagnosticsEngine::Error, | 
| Alexander Kornienko | 276a209 | 2013-01-11 16:03:45 +0000 | [diff] [blame] | 174 |                                          "unexpected '}'")); | 
| Manuel Klimek | a5342db | 2013-01-06 20:07:31 +0000 | [diff] [blame] | 175 |         Error = true; | 
 | 176 |         nextToken(); | 
 | 177 |         addUnwrappedLine(); | 
 | 178 |       } | 
 | 179 |       break; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 180 |     default: | 
| Manuel Klimek | f0ab0a3 | 2013-01-07 14:56:16 +0000 | [diff] [blame] | 181 |       parseStructuralElement(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 182 |       break; | 
 | 183 |     } | 
 | 184 |   } while (!eof()); | 
| Alexander Kornienko | cff563c | 2012-12-04 17:27:50 +0000 | [diff] [blame] | 185 |   return Error; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 186 | } | 
 | 187 |  | 
| Nico Weber | d74fcdb | 2013-02-10 20:35:35 +0000 | [diff] [blame] | 188 | bool UnwrappedLineParser::parseBlock(bool MustBeDeclaration, | 
 | 189 |                                      unsigned AddLevels) { | 
| Alexander Kornienko | a3a2b3a | 2012-12-06 17:49:17 +0000 | [diff] [blame] | 190 |   assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected"); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 191 |   nextToken(); | 
 | 192 |  | 
| Manuel Klimek | 2f1ac41 | 2013-01-21 16:42:44 +0000 | [diff] [blame] | 193 |   addUnwrappedLine(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 194 |  | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 195 |   ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, | 
 | 196 |                                           MustBeDeclaration); | 
| Manuel Klimek | 2f1ac41 | 2013-01-21 16:42:44 +0000 | [diff] [blame] | 197 |   Line->Level += AddLevels; | 
 | 198 |   parseLevel(/*HasOpeningBrace=*/true); | 
| Alexander Kornienko | 1575731 | 2012-12-06 18:03:27 +0000 | [diff] [blame] | 199 |  | 
| Manuel Klimek | 86721d2 | 2013-01-22 16:31:55 +0000 | [diff] [blame] | 200 |   if (!FormatTok.Tok.is(tok::r_brace)) { | 
 | 201 |     Line->Level -= AddLevels; | 
| Manuel Klimek | 2f1ac41 | 2013-01-21 16:42:44 +0000 | [diff] [blame] | 202 |     return true; | 
| Manuel Klimek | 86721d2 | 2013-01-22 16:31:55 +0000 | [diff] [blame] | 203 |   } | 
| Alexander Kornienko | 393b008 | 2012-12-04 15:40:36 +0000 | [diff] [blame] | 204 |  | 
| Manuel Klimek | de76854 | 2013-01-07 18:10:23 +0000 | [diff] [blame] | 205 |   nextToken();  // Munch the closing brace. | 
| Manuel Klimek | 86721d2 | 2013-01-22 16:31:55 +0000 | [diff] [blame] | 206 |   Line->Level -= AddLevels; | 
| Alexander Kornienko | cff563c | 2012-12-04 17:27:50 +0000 | [diff] [blame] | 207 |   return false; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 208 | } | 
 | 209 |  | 
 | 210 | void UnwrappedLineParser::parsePPDirective() { | 
| Manuel Klimek | a080a18 | 2013-01-02 16:30:12 +0000 | [diff] [blame] | 211 |   assert(FormatTok.Tok.is(tok::hash) && "'#' expected"); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 212 |   ScopedMacroState MacroState(*Line, Tokens, FormatTok); | 
| Manuel Klimek | a080a18 | 2013-01-02 16:30:12 +0000 | [diff] [blame] | 213 |   nextToken(); | 
 | 214 |  | 
| Manuel Klimek | a080a18 | 2013-01-02 16:30:12 +0000 | [diff] [blame] | 215 |   if (FormatTok.Tok.getIdentifierInfo() == NULL) { | 
| Manuel Klimek | bd04f2a | 2013-01-31 15:58:48 +0000 | [diff] [blame] | 216 |     parsePPUnknown(); | 
| Manuel Klimek | a080a18 | 2013-01-02 16:30:12 +0000 | [diff] [blame] | 217 |     return; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 218 |   } | 
| Manuel Klimek | a080a18 | 2013-01-02 16:30:12 +0000 | [diff] [blame] | 219 |  | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 220 |   switch (FormatTok.Tok.getIdentifierInfo()->getPPKeywordID()) { | 
 | 221 |   case tok::pp_define: | 
 | 222 |     parsePPDefine(); | 
 | 223 |     break; | 
 | 224 |   default: | 
 | 225 |     parsePPUnknown(); | 
 | 226 |     break; | 
 | 227 |   } | 
 | 228 | } | 
 | 229 |  | 
 | 230 | void UnwrappedLineParser::parsePPDefine() { | 
 | 231 |   nextToken(); | 
 | 232 |  | 
 | 233 |   if (FormatTok.Tok.getKind() != tok::identifier) { | 
 | 234 |     parsePPUnknown(); | 
 | 235 |     return; | 
 | 236 |   } | 
 | 237 |   nextToken(); | 
| Manuel Klimek | 7ccbc21 | 2013-01-23 14:37:36 +0000 | [diff] [blame] | 238 |   if (FormatTok.Tok.getKind() == tok::l_paren && | 
 | 239 |       FormatTok.WhiteSpaceLength == 0) { | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 240 |     parseParens(); | 
 | 241 |   } | 
 | 242 |   addUnwrappedLine(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 243 |   Line->Level = 1; | 
| Manuel Klimek | c3d0c82 | 2013-01-07 09:34:28 +0000 | [diff] [blame] | 244 |  | 
 | 245 |   // Errors during a preprocessor directive can only affect the layout of the | 
 | 246 |   // preprocessor directive, and thus we ignore them. An alternative approach | 
 | 247 |   // would be to use the same approach we use on the file level (no | 
 | 248 |   // re-indentation if there was a structural error) within the macro | 
 | 249 |   // definition. | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 250 |   parseFile(); | 
 | 251 | } | 
 | 252 |  | 
 | 253 | void UnwrappedLineParser::parsePPUnknown() { | 
| Manuel Klimek | a080a18 | 2013-01-02 16:30:12 +0000 | [diff] [blame] | 254 |   do { | 
| Manuel Klimek | a080a18 | 2013-01-02 16:30:12 +0000 | [diff] [blame] | 255 |     nextToken(); | 
 | 256 |   } while (!eof()); | 
 | 257 |   addUnwrappedLine(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 258 | } | 
 | 259 |  | 
| Manuel Klimek | f0ab0a3 | 2013-01-07 14:56:16 +0000 | [diff] [blame] | 260 | void UnwrappedLineParser::parseStructuralElement() { | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 261 |   assert(!FormatTok.Tok.is(tok::l_brace)); | 
| Dmitri Gribenko | 1f94f2b | 2012-12-30 21:27:25 +0000 | [diff] [blame] | 262 |   int TokenNumber = 0; | 
| Alexander Kornienko | a166e73 | 2012-12-04 14:46:19 +0000 | [diff] [blame] | 263 |   switch (FormatTok.Tok.getKind()) { | 
| Nico Weber | 6092d4e | 2013-01-07 19:05:19 +0000 | [diff] [blame] | 264 |   case tok::at: | 
 | 265 |     nextToken(); | 
| Nico Weber | d74fcdb | 2013-02-10 20:35:35 +0000 | [diff] [blame] | 266 |     if (FormatTok.Tok.is(tok::l_brace)) { | 
 | 267 |       parseBracedList(); | 
 | 268 |       break; | 
 | 269 |     } | 
| Nico Weber | 6092d4e | 2013-01-07 19:05:19 +0000 | [diff] [blame] | 270 |     switch (FormatTok.Tok.getObjCKeywordID()) { | 
 | 271 |     case tok::objc_public: | 
 | 272 |     case tok::objc_protected: | 
 | 273 |     case tok::objc_package: | 
 | 274 |     case tok::objc_private: | 
 | 275 |       return parseAccessSpecifier(); | 
| Nico Weber | 27d1367 | 2013-01-09 20:25:35 +0000 | [diff] [blame] | 276 |     case tok::objc_interface: | 
| Nico Weber | 50767d8 | 2013-01-09 23:25:37 +0000 | [diff] [blame] | 277 |     case tok::objc_implementation: | 
 | 278 |       return parseObjCInterfaceOrImplementation(); | 
| Nico Weber | 1abe6ea | 2013-01-09 21:15:03 +0000 | [diff] [blame] | 279 |     case tok::objc_protocol: | 
 | 280 |       return parseObjCProtocol(); | 
| Nico Weber | 049c447 | 2013-01-09 21:42:32 +0000 | [diff] [blame] | 281 |     case tok::objc_end: | 
 | 282 |       return; // Handled by the caller. | 
| Nico Weber | b530fa3 | 2013-01-10 00:25:19 +0000 | [diff] [blame] | 283 |     case tok::objc_optional: | 
 | 284 |     case tok::objc_required: | 
 | 285 |       nextToken(); | 
 | 286 |       addUnwrappedLine(); | 
 | 287 |       return; | 
| Nico Weber | 6092d4e | 2013-01-07 19:05:19 +0000 | [diff] [blame] | 288 |     default: | 
 | 289 |       break; | 
 | 290 |     } | 
 | 291 |     break; | 
| Alexander Kornienko | 1575731 | 2012-12-06 18:03:27 +0000 | [diff] [blame] | 292 |   case tok::kw_namespace: | 
 | 293 |     parseNamespace(); | 
 | 294 |     return; | 
| Dmitri Gribenko | 1f94f2b | 2012-12-30 21:27:25 +0000 | [diff] [blame] | 295 |   case tok::kw_inline: | 
 | 296 |     nextToken(); | 
 | 297 |     TokenNumber++; | 
 | 298 |     if (FormatTok.Tok.is(tok::kw_namespace)) { | 
 | 299 |       parseNamespace(); | 
 | 300 |       return; | 
 | 301 |     } | 
 | 302 |     break; | 
| Alexander Kornienko | a166e73 | 2012-12-04 14:46:19 +0000 | [diff] [blame] | 303 |   case tok::kw_public: | 
 | 304 |   case tok::kw_protected: | 
 | 305 |   case tok::kw_private: | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 306 |     parseAccessSpecifier(); | 
 | 307 |     return; | 
| Alexander Kornienko | a166e73 | 2012-12-04 14:46:19 +0000 | [diff] [blame] | 308 |   case tok::kw_if: | 
 | 309 |     parseIfThenElse(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 310 |     return; | 
| Alexander Kornienko | 2e97cfc | 2012-12-05 15:06:06 +0000 | [diff] [blame] | 311 |   case tok::kw_for: | 
 | 312 |   case tok::kw_while: | 
 | 313 |     parseForOrWhileLoop(); | 
 | 314 |     return; | 
| Alexander Kornienko | a166e73 | 2012-12-04 14:46:19 +0000 | [diff] [blame] | 315 |   case tok::kw_do: | 
 | 316 |     parseDoWhile(); | 
 | 317 |     return; | 
 | 318 |   case tok::kw_switch: | 
 | 319 |     parseSwitch(); | 
 | 320 |     return; | 
 | 321 |   case tok::kw_default: | 
 | 322 |     nextToken(); | 
 | 323 |     parseLabel(); | 
 | 324 |     return; | 
 | 325 |   case tok::kw_case: | 
 | 326 |     parseCaseLabel(); | 
 | 327 |     return; | 
| Manuel Klimek | c44ee89 | 2013-01-21 10:07:49 +0000 | [diff] [blame] | 328 |   case tok::kw_return: | 
 | 329 |     parseReturn(); | 
 | 330 |     return; | 
| Manuel Klimek | d19dc2d | 2013-01-21 14:32:05 +0000 | [diff] [blame] | 331 |   case tok::kw_extern: | 
 | 332 |     nextToken(); | 
 | 333 |     if (FormatTok.Tok.is(tok::string_literal)) { | 
 | 334 |       nextToken(); | 
 | 335 |       if (FormatTok.Tok.is(tok::l_brace)) { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 336 |         parseBlock(/*MustBeDeclaration=*/ true, 0); | 
| Manuel Klimek | d19dc2d | 2013-01-21 14:32:05 +0000 | [diff] [blame] | 337 |         addUnwrappedLine(); | 
 | 338 |         return; | 
 | 339 |       } | 
 | 340 |     } | 
 | 341 |     // In all other cases, parse the declaration. | 
 | 342 |     break; | 
| Alexander Kornienko | a166e73 | 2012-12-04 14:46:19 +0000 | [diff] [blame] | 343 |   default: | 
 | 344 |     break; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 345 |   } | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 346 |   do { | 
 | 347 |     ++TokenNumber; | 
 | 348 |     switch (FormatTok.Tok.getKind()) { | 
| Nico Weber | d74fcdb | 2013-02-10 20:35:35 +0000 | [diff] [blame] | 349 |     case tok::at: | 
 | 350 |       nextToken(); | 
 | 351 |       if (FormatTok.Tok.is(tok::l_brace)) | 
 | 352 |         parseBracedList(); | 
 | 353 |       break; | 
| Alexander Kornienko | a166e73 | 2012-12-04 14:46:19 +0000 | [diff] [blame] | 354 |     case tok::kw_enum: | 
 | 355 |       parseEnum(); | 
| Manuel Klimek | 308232c | 2013-01-21 19:17:52 +0000 | [diff] [blame] | 356 |       break; | 
| Alexander Kornienko | d881875 | 2013-01-16 11:43:46 +0000 | [diff] [blame] | 357 |     case tok::kw_struct: | 
 | 358 |     case tok::kw_union: | 
| Manuel Klimek | de76854 | 2013-01-07 18:10:23 +0000 | [diff] [blame] | 359 |     case tok::kw_class: | 
| Manuel Klimek | 47ea7f6 | 2013-01-15 13:38:33 +0000 | [diff] [blame] | 360 |       parseRecord(); | 
 | 361 |       // A record declaration or definition is always the start of a structural | 
 | 362 |       // element. | 
 | 363 |       break; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 364 |     case tok::semi: | 
 | 365 |       nextToken(); | 
 | 366 |       addUnwrappedLine(); | 
 | 367 |       return; | 
| Alexander Kornienko | d881875 | 2013-01-16 11:43:46 +0000 | [diff] [blame] | 368 |     case tok::r_brace: | 
 | 369 |       addUnwrappedLine(); | 
 | 370 |       return; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 371 |     case tok::l_paren: | 
 | 372 |       parseParens(); | 
 | 373 |       break; | 
 | 374 |     case tok::l_brace: | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 375 |       // A block outside of parentheses must be the last part of a | 
 | 376 |       // structural element. | 
 | 377 |       // FIXME: Figure out cases where this is not true, and add projections for | 
 | 378 |       // them (the one we know is missing are lambdas). | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 379 |       parseBlock(/*MustBeDeclaration=*/ false); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 380 |       addUnwrappedLine(); | 
 | 381 |       return; | 
| Alexander Kornienko | a166e73 | 2012-12-04 14:46:19 +0000 | [diff] [blame] | 382 |     case tok::identifier: | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 383 |       nextToken(); | 
 | 384 |       if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) { | 
 | 385 |         parseLabel(); | 
 | 386 |         return; | 
 | 387 |       } | 
 | 388 |       break; | 
| Daniel Jasper | 05b1ac8 | 2012-12-17 11:29:41 +0000 | [diff] [blame] | 389 |     case tok::equal: | 
 | 390 |       nextToken(); | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 391 |       if (FormatTok.Tok.is(tok::l_brace)) { | 
 | 392 |         parseBracedList(); | 
 | 393 |       } | 
| Daniel Jasper | 05b1ac8 | 2012-12-17 11:29:41 +0000 | [diff] [blame] | 394 |       break; | 
| Alexander Kornienko | a166e73 | 2012-12-04 14:46:19 +0000 | [diff] [blame] | 395 |     default: | 
 | 396 |       nextToken(); | 
 | 397 |       break; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 398 |     } | 
 | 399 |   } while (!eof()); | 
 | 400 | } | 
 | 401 |  | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 402 | void UnwrappedLineParser::parseBracedList() { | 
 | 403 |   nextToken(); | 
 | 404 |  | 
 | 405 |   do { | 
 | 406 |     switch (FormatTok.Tok.getKind()) { | 
 | 407 |     case tok::l_brace: | 
 | 408 |       parseBracedList(); | 
 | 409 |       break; | 
 | 410 |     case tok::r_brace: | 
 | 411 |       nextToken(); | 
 | 412 |       return; | 
 | 413 |     default: | 
 | 414 |       nextToken(); | 
 | 415 |       break; | 
 | 416 |     } | 
 | 417 |   } while (!eof()); | 
 | 418 | } | 
 | 419 |  | 
| Manuel Klimek | c44ee89 | 2013-01-21 10:07:49 +0000 | [diff] [blame] | 420 | void UnwrappedLineParser::parseReturn() { | 
 | 421 |   nextToken(); | 
 | 422 |  | 
 | 423 |   do { | 
 | 424 |     switch (FormatTok.Tok.getKind()) { | 
 | 425 |     case tok::l_brace: | 
 | 426 |       parseBracedList(); | 
 | 427 |       break; | 
 | 428 |     case tok::l_paren: | 
 | 429 |       parseParens(); | 
 | 430 |       break; | 
 | 431 |     case tok::r_brace: | 
 | 432 |       // Assume missing ';'. | 
 | 433 |       addUnwrappedLine(); | 
 | 434 |       return; | 
 | 435 |     case tok::semi: | 
 | 436 |       nextToken(); | 
 | 437 |       addUnwrappedLine(); | 
 | 438 |       return; | 
 | 439 |     default: | 
 | 440 |       nextToken(); | 
 | 441 |       break; | 
 | 442 |     } | 
 | 443 |   } while (!eof()); | 
 | 444 | } | 
 | 445 |  | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 446 | void UnwrappedLineParser::parseParens() { | 
 | 447 |   assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected."); | 
 | 448 |   nextToken(); | 
 | 449 |   do { | 
 | 450 |     switch (FormatTok.Tok.getKind()) { | 
 | 451 |     case tok::l_paren: | 
 | 452 |       parseParens(); | 
 | 453 |       break; | 
 | 454 |     case tok::r_paren: | 
 | 455 |       nextToken(); | 
 | 456 |       return; | 
| Nico Weber | 2afbe52 | 2013-02-10 04:38:23 +0000 | [diff] [blame] | 457 |     case tok::l_brace: { | 
 | 458 |       nextToken(); | 
 | 459 |       ScopedLineState LineState(*this); | 
 | 460 |       ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack, | 
 | 461 |                                               /*MustBeDeclaration=*/ false); | 
 | 462 |       Line->Level += 1; | 
 | 463 |       parseLevel(/*HasOpeningBrace=*/ true); | 
 | 464 |       Line->Level -= 1; | 
| Manuel Klimek | bb42bf1 | 2013-01-10 11:52:21 +0000 | [diff] [blame] | 465 |       break; | 
| Nico Weber | 2afbe52 | 2013-02-10 04:38:23 +0000 | [diff] [blame] | 466 |     } | 
| Nico Weber | d74fcdb | 2013-02-10 20:35:35 +0000 | [diff] [blame] | 467 |     case tok::at: | 
 | 468 |       nextToken(); | 
 | 469 |       if (FormatTok.Tok.is(tok::l_brace)) | 
 | 470 |         parseBracedList(); | 
 | 471 |       break; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 472 |     default: | 
 | 473 |       nextToken(); | 
 | 474 |       break; | 
 | 475 |     } | 
 | 476 |   } while (!eof()); | 
 | 477 | } | 
 | 478 |  | 
 | 479 | void UnwrappedLineParser::parseIfThenElse() { | 
 | 480 |   assert(FormatTok.Tok.is(tok::kw_if) && "'if' expected"); | 
 | 481 |   nextToken(); | 
| Manuel Klimek | d465843 | 2013-01-11 18:28:36 +0000 | [diff] [blame] | 482 |   if (FormatTok.Tok.is(tok::l_paren)) | 
 | 483 |     parseParens(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 484 |   bool NeedsUnwrappedLine = false; | 
 | 485 |   if (FormatTok.Tok.is(tok::l_brace)) { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 486 |     parseBlock(/*MustBeDeclaration=*/ false); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 487 |     NeedsUnwrappedLine = true; | 
 | 488 |   } else { | 
 | 489 |     addUnwrappedLine(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 490 |     ++Line->Level; | 
| Manuel Klimek | f0ab0a3 | 2013-01-07 14:56:16 +0000 | [diff] [blame] | 491 |     parseStructuralElement(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 492 |     --Line->Level; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 493 |   } | 
 | 494 |   if (FormatTok.Tok.is(tok::kw_else)) { | 
 | 495 |     nextToken(); | 
 | 496 |     if (FormatTok.Tok.is(tok::l_brace)) { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 497 |       parseBlock(/*MustBeDeclaration=*/ false); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 498 |       addUnwrappedLine(); | 
 | 499 |     } else if (FormatTok.Tok.is(tok::kw_if)) { | 
 | 500 |       parseIfThenElse(); | 
 | 501 |     } else { | 
 | 502 |       addUnwrappedLine(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 503 |       ++Line->Level; | 
| Manuel Klimek | f0ab0a3 | 2013-01-07 14:56:16 +0000 | [diff] [blame] | 504 |       parseStructuralElement(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 505 |       --Line->Level; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 506 |     } | 
 | 507 |   } else if (NeedsUnwrappedLine) { | 
 | 508 |     addUnwrappedLine(); | 
 | 509 |   } | 
 | 510 | } | 
 | 511 |  | 
| Alexander Kornienko | 1575731 | 2012-12-06 18:03:27 +0000 | [diff] [blame] | 512 | void UnwrappedLineParser::parseNamespace() { | 
 | 513 |   assert(FormatTok.Tok.is(tok::kw_namespace) && "'namespace' expected"); | 
 | 514 |   nextToken(); | 
 | 515 |   if (FormatTok.Tok.is(tok::identifier)) | 
 | 516 |     nextToken(); | 
 | 517 |   if (FormatTok.Tok.is(tok::l_brace)) { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 518 |     parseBlock(/*MustBeDeclaration=*/ true, 0); | 
| Manuel Klimek | 7fc2db0 | 2013-02-06 16:08:09 +0000 | [diff] [blame] | 519 |     // Munch the semicolon after a namespace. This is more common than one would | 
 | 520 |     // think. Puttin the semicolon into its own line is very ugly. | 
 | 521 |     if (FormatTok.Tok.is(tok::semi)) | 
 | 522 |       nextToken(); | 
| Alexander Kornienko | 1575731 | 2012-12-06 18:03:27 +0000 | [diff] [blame] | 523 |     addUnwrappedLine(); | 
 | 524 |   } | 
 | 525 |   // FIXME: Add error handling. | 
 | 526 | } | 
 | 527 |  | 
| Alexander Kornienko | 2e97cfc | 2012-12-05 15:06:06 +0000 | [diff] [blame] | 528 | void UnwrappedLineParser::parseForOrWhileLoop() { | 
 | 529 |   assert((FormatTok.Tok.is(tok::kw_for) || FormatTok.Tok.is(tok::kw_while)) && | 
 | 530 |          "'for' or 'while' expected"); | 
 | 531 |   nextToken(); | 
| Manuel Klimek | 6eca03f | 2013-01-11 19:23:05 +0000 | [diff] [blame] | 532 |   if (FormatTok.Tok.is(tok::l_paren)) | 
 | 533 |     parseParens(); | 
| Alexander Kornienko | 2e97cfc | 2012-12-05 15:06:06 +0000 | [diff] [blame] | 534 |   if (FormatTok.Tok.is(tok::l_brace)) { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 535 |     parseBlock(/*MustBeDeclaration=*/ false); | 
| Alexander Kornienko | 2e97cfc | 2012-12-05 15:06:06 +0000 | [diff] [blame] | 536 |     addUnwrappedLine(); | 
 | 537 |   } else { | 
 | 538 |     addUnwrappedLine(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 539 |     ++Line->Level; | 
| Manuel Klimek | f0ab0a3 | 2013-01-07 14:56:16 +0000 | [diff] [blame] | 540 |     parseStructuralElement(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 541 |     --Line->Level; | 
| Alexander Kornienko | 2e97cfc | 2012-12-05 15:06:06 +0000 | [diff] [blame] | 542 |   } | 
 | 543 | } | 
 | 544 |  | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 545 | void UnwrappedLineParser::parseDoWhile() { | 
 | 546 |   assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected"); | 
 | 547 |   nextToken(); | 
 | 548 |   if (FormatTok.Tok.is(tok::l_brace)) { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 549 |     parseBlock(/*MustBeDeclaration=*/ false); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 550 |   } else { | 
 | 551 |     addUnwrappedLine(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 552 |     ++Line->Level; | 
| Manuel Klimek | f0ab0a3 | 2013-01-07 14:56:16 +0000 | [diff] [blame] | 553 |     parseStructuralElement(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 554 |     --Line->Level; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 555 |   } | 
 | 556 |  | 
| Alexander Kornienko | 393b008 | 2012-12-04 15:40:36 +0000 | [diff] [blame] | 557 |   // FIXME: Add error handling. | 
 | 558 |   if (!FormatTok.Tok.is(tok::kw_while)) { | 
 | 559 |     addUnwrappedLine(); | 
 | 560 |     return; | 
 | 561 |   } | 
 | 562 |  | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 563 |   nextToken(); | 
| Manuel Klimek | f0ab0a3 | 2013-01-07 14:56:16 +0000 | [diff] [blame] | 564 |   parseStructuralElement(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 565 | } | 
 | 566 |  | 
 | 567 | void UnwrappedLineParser::parseLabel() { | 
 | 568 |   // FIXME: remove all asserts. | 
 | 569 |   assert(FormatTok.Tok.is(tok::colon) && "':' expected"); | 
 | 570 |   nextToken(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 571 |   unsigned OldLineLevel = Line->Level; | 
 | 572 |   if (Line->Level > 0) | 
 | 573 |     --Line->Level; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 574 |   if (FormatTok.Tok.is(tok::l_brace)) { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 575 |     parseBlock(/*MustBeDeclaration=*/ false); | 
| Nico Weber | 94fb729 | 2013-01-18 05:50:57 +0000 | [diff] [blame] | 576 |     if (FormatTok.Tok.is(tok::kw_break)) | 
 | 577 |       parseStructuralElement(); // "break;" after "}" goes on the same line. | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 578 |   } | 
 | 579 |   addUnwrappedLine(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 580 |   Line->Level = OldLineLevel; | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 581 | } | 
 | 582 |  | 
 | 583 | void UnwrappedLineParser::parseCaseLabel() { | 
 | 584 |   assert(FormatTok.Tok.is(tok::kw_case) && "'case' expected"); | 
 | 585 |   // FIXME: fix handling of complex expressions here. | 
 | 586 |   do { | 
 | 587 |     nextToken(); | 
 | 588 |   } while (!eof() && !FormatTok.Tok.is(tok::colon)); | 
 | 589 |   parseLabel(); | 
 | 590 | } | 
 | 591 |  | 
 | 592 | void UnwrappedLineParser::parseSwitch() { | 
 | 593 |   assert(FormatTok.Tok.is(tok::kw_switch) && "'switch' expected"); | 
 | 594 |   nextToken(); | 
| Manuel Klimek | 6eca03f | 2013-01-11 19:23:05 +0000 | [diff] [blame] | 595 |   if (FormatTok.Tok.is(tok::l_paren)) | 
 | 596 |     parseParens(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 597 |   if (FormatTok.Tok.is(tok::l_brace)) { | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 598 |     parseBlock(/*MustBeDeclaration=*/ false, Style.IndentCaseLabels ? 2 : 1); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 599 |     addUnwrappedLine(); | 
 | 600 |   } else { | 
 | 601 |     addUnwrappedLine(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 602 |     Line->Level += (Style.IndentCaseLabels ? 2 : 1); | 
| Manuel Klimek | f0ab0a3 | 2013-01-07 14:56:16 +0000 | [diff] [blame] | 603 |     parseStructuralElement(); | 
| Manuel Klimek | 526ed11 | 2013-01-09 15:25:02 +0000 | [diff] [blame] | 604 |     Line->Level -= (Style.IndentCaseLabels ? 2 : 1); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 605 |   } | 
 | 606 | } | 
 | 607 |  | 
 | 608 | void UnwrappedLineParser::parseAccessSpecifier() { | 
 | 609 |   nextToken(); | 
| Alexander Kornienko | 56e49c5 | 2012-12-10 16:34:48 +0000 | [diff] [blame] | 610 |   // Otherwise, we don't know what it is, and we'd better keep the next token. | 
 | 611 |   if (FormatTok.Tok.is(tok::colon)) | 
 | 612 |     nextToken(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 613 |   addUnwrappedLine(); | 
 | 614 | } | 
 | 615 |  | 
 | 616 | void UnwrappedLineParser::parseEnum() { | 
| Manuel Klimek | 308232c | 2013-01-21 19:17:52 +0000 | [diff] [blame] | 617 |   nextToken(); | 
 | 618 |   if (FormatTok.Tok.is(tok::identifier) || | 
 | 619 |       FormatTok.Tok.is(tok::kw___attribute) || | 
 | 620 |       FormatTok.Tok.is(tok::kw___declspec)) { | 
 | 621 |     nextToken(); | 
 | 622 |     // We can have macros or attributes in between 'enum' and the enum name. | 
 | 623 |     if (FormatTok.Tok.is(tok::l_paren)) { | 
| Alexander Kornienko | a166e73 | 2012-12-04 14:46:19 +0000 | [diff] [blame] | 624 |       parseParens(); | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 625 |     } | 
| Manuel Klimek | 308232c | 2013-01-21 19:17:52 +0000 | [diff] [blame] | 626 |     if (FormatTok.Tok.is(tok::identifier)) | 
 | 627 |       nextToken(); | 
 | 628 |   } | 
 | 629 |   if (FormatTok.Tok.is(tok::l_brace)) { | 
 | 630 |     nextToken(); | 
 | 631 |     addUnwrappedLine(); | 
 | 632 |     ++Line->Level; | 
 | 633 |     do { | 
 | 634 |       switch (FormatTok.Tok.getKind()) { | 
| Manuel Klimek | 308232c | 2013-01-21 19:17:52 +0000 | [diff] [blame] | 635 |       case tok::l_paren: | 
 | 636 |         parseParens(); | 
 | 637 |         break; | 
 | 638 |       case tok::r_brace: | 
 | 639 |         addUnwrappedLine(); | 
 | 640 |         nextToken(); | 
 | 641 |         --Line->Level; | 
 | 642 |         return; | 
 | 643 |       case tok::comma: | 
 | 644 |         nextToken(); | 
 | 645 |         addUnwrappedLine(); | 
 | 646 |         break; | 
 | 647 |       default: | 
 | 648 |         nextToken(); | 
 | 649 |         break; | 
 | 650 |       } | 
 | 651 |     } while (!eof()); | 
 | 652 |   } | 
 | 653 |   // We fall through to parsing a structural element afterwards, so that in | 
 | 654 |   // enum A {} n, m; | 
 | 655 |   // "} n, m;" will end up in one unwrapped line. | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 656 | } | 
 | 657 |  | 
| Manuel Klimek | 47ea7f6 | 2013-01-15 13:38:33 +0000 | [diff] [blame] | 658 | void UnwrappedLineParser::parseRecord() { | 
| Manuel Klimek | de76854 | 2013-01-07 18:10:23 +0000 | [diff] [blame] | 659 |   nextToken(); | 
| Manuel Klimek | 47ea7f6 | 2013-01-15 13:38:33 +0000 | [diff] [blame] | 660 |   if (FormatTok.Tok.is(tok::identifier) || | 
 | 661 |       FormatTok.Tok.is(tok::kw___attribute) || | 
 | 662 |       FormatTok.Tok.is(tok::kw___declspec)) { | 
 | 663 |     nextToken(); | 
 | 664 |     // We can have macros or attributes in between 'class' and the class name. | 
 | 665 |     if (FormatTok.Tok.is(tok::l_paren)) { | 
 | 666 |       parseParens(); | 
| Manuel Klimek | de76854 | 2013-01-07 18:10:23 +0000 | [diff] [blame] | 667 |     } | 
| Manuel Klimek | b8b1ce1 | 2013-02-06 15:57:54 +0000 | [diff] [blame] | 668 |     // The actual identifier can be a nested name specifier, and in macros | 
 | 669 |     // it is often token-pasted. | 
| Manuel Klimek | 7f5b025 | 2013-01-21 10:17:14 +0000 | [diff] [blame] | 670 |     while (FormatTok.Tok.is(tok::identifier) || | 
| Manuel Klimek | b8b1ce1 | 2013-02-06 15:57:54 +0000 | [diff] [blame] | 671 |            FormatTok.Tok.is(tok::coloncolon) || | 
 | 672 |            FormatTok.Tok.is(tok::hashhash)) | 
| Manuel Klimek | 47ea7f6 | 2013-01-15 13:38:33 +0000 | [diff] [blame] | 673 |       nextToken(); | 
 | 674 |  | 
| Manuel Klimek | 3a3408c | 2013-01-21 13:58:54 +0000 | [diff] [blame] | 675 |     // Note that parsing away template declarations here leads to incorrectly | 
 | 676 |     // accepting function declarations as record declarations. | 
 | 677 |     // In general, we cannot solve this problem. Consider: | 
 | 678 |     // class A<int> B() {} | 
 | 679 |     // which can be a function definition or a class definition when B() is a | 
 | 680 |     // macro. If we find enough real-world cases where this is a problem, we | 
 | 681 |     // can parse for the 'template' keyword in the beginning of the statement, | 
 | 682 |     // and thus rule out the record production in case there is no template | 
 | 683 |     // (this would still leave us with an ambiguity between template function | 
 | 684 |     // and class declarations). | 
 | 685 |     if (FormatTok.Tok.is(tok::colon) || FormatTok.Tok.is(tok::less)) { | 
| Manuel Klimek | 47ea7f6 | 2013-01-15 13:38:33 +0000 | [diff] [blame] | 686 |       while (FormatTok.Tok.isNot(tok::l_brace)) { | 
 | 687 |         if (FormatTok.Tok.is(tok::semi)) | 
 | 688 |           return; | 
 | 689 |         nextToken(); | 
 | 690 |       } | 
 | 691 |     } | 
 | 692 |   } | 
 | 693 |   if (FormatTok.Tok.is(tok::l_brace)) | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 694 |     parseBlock(/*MustBeDeclaration=*/ true); | 
| Manuel Klimek | 3a3408c | 2013-01-21 13:58:54 +0000 | [diff] [blame] | 695 |   // We fall through to parsing a structural element afterwards, so | 
 | 696 |   // class A {} n, m; | 
 | 697 |   // will end up in one unwrapped line. | 
| Manuel Klimek | de76854 | 2013-01-07 18:10:23 +0000 | [diff] [blame] | 698 | } | 
 | 699 |  | 
| Nico Weber | 1abe6ea | 2013-01-09 21:15:03 +0000 | [diff] [blame] | 700 | void UnwrappedLineParser::parseObjCProtocolList() { | 
 | 701 |   assert(FormatTok.Tok.is(tok::less) && "'<' expected."); | 
 | 702 |   do | 
 | 703 |     nextToken(); | 
 | 704 |   while (!eof() && FormatTok.Tok.isNot(tok::greater)); | 
 | 705 |   nextToken(); // Skip '>'. | 
 | 706 | } | 
 | 707 |  | 
 | 708 | void UnwrappedLineParser::parseObjCUntilAtEnd() { | 
 | 709 |   do { | 
 | 710 |     if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) { | 
 | 711 |       nextToken(); | 
 | 712 |       addUnwrappedLine(); | 
 | 713 |       break; | 
 | 714 |     } | 
 | 715 |     parseStructuralElement(); | 
 | 716 |   } while (!eof()); | 
 | 717 | } | 
 | 718 |  | 
| Nico Weber | 50767d8 | 2013-01-09 23:25:37 +0000 | [diff] [blame] | 719 | void UnwrappedLineParser::parseObjCInterfaceOrImplementation() { | 
| Nico Weber | 27d1367 | 2013-01-09 20:25:35 +0000 | [diff] [blame] | 720 |   nextToken(); | 
 | 721 |   nextToken();  // interface name | 
 | 722 |  | 
 | 723 |   // @interface can be followed by either a base class, or a category. | 
 | 724 |   if (FormatTok.Tok.is(tok::colon)) { | 
 | 725 |     nextToken(); | 
 | 726 |     nextToken();  // base class name | 
 | 727 |   } else if (FormatTok.Tok.is(tok::l_paren)) | 
 | 728 |     // Skip category, if present. | 
 | 729 |     parseParens(); | 
 | 730 |  | 
| Nico Weber | 1abe6ea | 2013-01-09 21:15:03 +0000 | [diff] [blame] | 731 |   if (FormatTok.Tok.is(tok::less)) | 
 | 732 |     parseObjCProtocolList(); | 
| Nico Weber | 27d1367 | 2013-01-09 20:25:35 +0000 | [diff] [blame] | 733 |  | 
 | 734 |   // If instance variables are present, keep the '{' on the first line too. | 
 | 735 |   if (FormatTok.Tok.is(tok::l_brace)) | 
| Manuel Klimek | 70b03f4 | 2013-01-23 09:32:48 +0000 | [diff] [blame] | 736 |     parseBlock(/*MustBeDeclaration=*/ true); | 
| Nico Weber | 27d1367 | 2013-01-09 20:25:35 +0000 | [diff] [blame] | 737 |  | 
 | 738 |   // With instance variables, this puts '}' on its own line.  Without instance | 
 | 739 |   // variables, this ends the @interface line. | 
 | 740 |   addUnwrappedLine(); | 
 | 741 |  | 
| Nico Weber | 1abe6ea | 2013-01-09 21:15:03 +0000 | [diff] [blame] | 742 |   parseObjCUntilAtEnd(); | 
 | 743 | } | 
| Nico Weber | 27d1367 | 2013-01-09 20:25:35 +0000 | [diff] [blame] | 744 |  | 
| Nico Weber | 1abe6ea | 2013-01-09 21:15:03 +0000 | [diff] [blame] | 745 | void UnwrappedLineParser::parseObjCProtocol() { | 
 | 746 |   nextToken(); | 
 | 747 |   nextToken();  // protocol name | 
 | 748 |  | 
 | 749 |   if (FormatTok.Tok.is(tok::less)) | 
 | 750 |     parseObjCProtocolList(); | 
 | 751 |  | 
 | 752 |   // Check for protocol declaration. | 
 | 753 |   if (FormatTok.Tok.is(tok::semi)) { | 
 | 754 |     nextToken(); | 
 | 755 |     return addUnwrappedLine(); | 
 | 756 |   } | 
 | 757 |  | 
 | 758 |   addUnwrappedLine(); | 
 | 759 |   parseObjCUntilAtEnd(); | 
| Nico Weber | 27d1367 | 2013-01-09 20:25:35 +0000 | [diff] [blame] | 760 | } | 
 | 761 |  | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 762 | void UnwrappedLineParser::addUnwrappedLine() { | 
| Daniel Jasper | cbb6c41 | 2013-01-16 09:10:19 +0000 | [diff] [blame] | 763 |   if (Line->Tokens.empty()) | 
| Daniel Jasper | 26f7e78 | 2013-01-08 14:56:18 +0000 | [diff] [blame] | 764 |     return; | 
| Manuel Klimek | 8fa3799 | 2013-01-16 12:31:12 +0000 | [diff] [blame] | 765 |   DEBUG({ | 
| Manuel Klimek | a28fc06 | 2013-02-11 12:33:24 +0000 | [diff] [blame] | 766 |     llvm::dbgs() << "Line(" << Line->Level << ")" | 
 | 767 |                  << (Line->InPPDirective ? " MACRO" : "") << ": "; | 
| Manuel Klimek | 8fa3799 | 2013-01-16 12:31:12 +0000 | [diff] [blame] | 768 |     for (std::list<FormatToken>::iterator I = Line->Tokens.begin(), | 
 | 769 |                                           E = Line->Tokens.end(); | 
 | 770 |          I != E; ++I) { | 
 | 771 |       llvm::dbgs() << I->Tok.getName() << " "; | 
| Daniel Jasper | cbb6c41 | 2013-01-16 09:10:19 +0000 | [diff] [blame] | 772 |  | 
| Manuel Klimek | 8fa3799 | 2013-01-16 12:31:12 +0000 | [diff] [blame] | 773 |     } | 
 | 774 |     llvm::dbgs() << "\n"; | 
 | 775 |   }); | 
| Manuel Klimek | 525fe16 | 2013-01-18 14:04:34 +0000 | [diff] [blame] | 776 |   CurrentLines->push_back(*Line); | 
| Daniel Jasper | cbb6c41 | 2013-01-16 09:10:19 +0000 | [diff] [blame] | 777 |   Line->Tokens.clear(); | 
| Manuel Klimek | 525fe16 | 2013-01-18 14:04:34 +0000 | [diff] [blame] | 778 |   if (CurrentLines == &Lines && !PreprocessorDirectives.empty()) { | 
 | 779 |     for (std::vector<UnwrappedLine>::iterator I = PreprocessorDirectives | 
 | 780 |              .begin(), E = PreprocessorDirectives.end(); | 
 | 781 |          I != E; ++I) { | 
 | 782 |       CurrentLines->push_back(*I); | 
 | 783 |     } | 
 | 784 |     PreprocessorDirectives.clear(); | 
 | 785 |   } | 
 | 786 |  | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 787 | } | 
 | 788 |  | 
 | 789 | bool UnwrappedLineParser::eof() const { | 
 | 790 |   return FormatTok.Tok.is(tok::eof); | 
 | 791 | } | 
 | 792 |  | 
| Manuel Klimek | 86721d2 | 2013-01-22 16:31:55 +0000 | [diff] [blame] | 793 | void UnwrappedLineParser::flushComments(bool NewlineBeforeNext) { | 
 | 794 |   bool JustComments = Line->Tokens.empty(); | 
 | 795 |   for (SmallVectorImpl<FormatToken>::const_iterator | 
 | 796 |            I = CommentsBeforeNextToken.begin(), | 
 | 797 |            E = CommentsBeforeNextToken.end(); | 
 | 798 |        I != E; ++I) { | 
| Manuel Klimek | b3507cd | 2013-02-06 16:40:56 +0000 | [diff] [blame] | 799 |     if (I->NewlinesBefore && JustComments) { | 
| Manuel Klimek | 86721d2 | 2013-01-22 16:31:55 +0000 | [diff] [blame] | 800 |       addUnwrappedLine(); | 
 | 801 |     } | 
 | 802 |     pushToken(*I); | 
 | 803 |   } | 
 | 804 |   if (NewlineBeforeNext && JustComments) { | 
 | 805 |     addUnwrappedLine(); | 
 | 806 |   } | 
 | 807 |   CommentsBeforeNextToken.clear(); | 
 | 808 | } | 
 | 809 |  | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 810 | void UnwrappedLineParser::nextToken() { | 
 | 811 |   if (eof()) | 
 | 812 |     return; | 
| Manuel Klimek | b3507cd | 2013-02-06 16:40:56 +0000 | [diff] [blame] | 813 |   flushComments(FormatTok.NewlinesBefore > 0); | 
| Manuel Klimek | 86721d2 | 2013-01-22 16:31:55 +0000 | [diff] [blame] | 814 |   pushToken(FormatTok); | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 815 |   readToken(); | 
 | 816 | } | 
 | 817 |  | 
 | 818 | void UnwrappedLineParser::readToken() { | 
| Manuel Klimek | 86721d2 | 2013-01-22 16:31:55 +0000 | [diff] [blame] | 819 |   bool CommentsInCurrentLine = true; | 
 | 820 |   do { | 
 | 821 |     FormatTok = Tokens->getNextToken(); | 
 | 822 |     while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) && | 
 | 823 |            ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) || | 
 | 824 |             FormatTok.IsFirst)) { | 
 | 825 |       // If there is an unfinished unwrapped line, we flush the preprocessor | 
 | 826 |       // directives only after that unwrapped line was finished later. | 
 | 827 |       bool SwitchToPreprocessorLines = !Line->Tokens.empty() && | 
 | 828 |                                        CurrentLines == &Lines; | 
 | 829 |       ScopedLineState BlockState(*this, SwitchToPreprocessorLines); | 
 | 830 |       parsePPDirective(); | 
 | 831 |     } | 
 | 832 |     if (!FormatTok.Tok.is(tok::comment)) | 
 | 833 |       return; | 
| Manuel Klimek | b3507cd | 2013-02-06 16:40:56 +0000 | [diff] [blame] | 834 |     if (FormatTok.NewlinesBefore > 0 || FormatTok.IsFirst) { | 
| Manuel Klimek | 86721d2 | 2013-01-22 16:31:55 +0000 | [diff] [blame] | 835 |       CommentsInCurrentLine = false; | 
 | 836 |     } | 
 | 837 |     if (CommentsInCurrentLine) { | 
 | 838 |       pushToken(FormatTok); | 
 | 839 |     } else { | 
 | 840 |       CommentsBeforeNextToken.push_back(FormatTok); | 
 | 841 |     } | 
 | 842 |   } while (!eof()); | 
 | 843 | } | 
 | 844 |  | 
 | 845 | void UnwrappedLineParser::pushToken(const FormatToken &Tok) { | 
 | 846 |   Line->Tokens.push_back(Tok); | 
 | 847 |   if (MustBreakBeforeNextToken) { | 
 | 848 |     Line->Tokens.back().MustBreakBefore = true; | 
 | 849 |     MustBreakBeforeNextToken = false; | 
| Manuel Klimek | d4397b9 | 2013-01-04 23:34:14 +0000 | [diff] [blame] | 850 |   } | 
| Daniel Jasper | bac016b | 2012-12-03 18:12:45 +0000 | [diff] [blame] | 851 | } | 
 | 852 |  | 
| Daniel Jasper | cd16238 | 2013-01-07 13:26:07 +0000 | [diff] [blame] | 853 | } // end namespace format | 
 | 854 | } // end namespace clang |