1 //===--- CommentBriefParser.cpp - Dumb comment parser ---------------------===// 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 #include "clang/AST/CommentBriefParser.h" 11 #include "clang/AST/CommentCommandTraits.h" 12 #include "llvm/ADT/StringSwitch.h" 13 14 namespace clang { 15 namespace comments { 16 17 namespace { 18 /// Convert all whitespace into spaces, remove leading and trailing spaces, 19 /// compress multiple spaces into one. 20 void cleanupBrief(std::string &S) { 21 bool PrevWasSpace = true; 22 std::string::iterator O = S.begin(); 23 for (std::string::iterator I = S.begin(), E = S.end(); 24 I != E; ++I) { 25 const char C = *I; 26 if (C == ' ' || C == '\n' || C == '\r' || 27 C == '\t' || C == '\v' || C == '\f') { 28 if (!PrevWasSpace) { 29 *O++ = ' '; 30 PrevWasSpace = true; 31 } 32 continue; 33 } else { 34 *O++ = C; 35 PrevWasSpace = false; 36 } 37 } 38 if (O != S.begin() && *(O - 1) == ' ') 39 --O; 40 41 S.resize(O - S.begin()); 42 } 43 } // unnamed namespace 44 45 BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) : 46 L(L), Traits(Traits) { 47 // Get lookahead token. 48 ConsumeToken(); 49 } 50 51 std::string BriefParser::Parse() { 52 std::string FirstParagraphOrBrief; 53 std::string ReturnsParagraph; 54 bool InFirstParagraph = true; 55 bool InBrief = false; 56 bool InReturns = false; 57 58 while (Tok.isNot(tok::eof)) { 59 if (Tok.is(tok::text)) { 60 if (InFirstParagraph || InBrief) 61 FirstParagraphOrBrief += Tok.getText(); 62 else if (InReturns) 63 ReturnsParagraph += Tok.getText(); 64 ConsumeToken(); 65 continue; 66 } 67 68 if (Tok.is(tok::command)) { 69 StringRef Name = Tok.getCommandName(); 70 if (Traits.isBriefCommand(Name)) { 71 FirstParagraphOrBrief.clear(); 72 InBrief = true; 73 ConsumeToken(); 74 continue; 75 } 76 if (Traits.isReturnsCommand(Name)) { 77 InReturns = true; 78 ReturnsParagraph += "Returns "; 79 } 80 // Block commands implicitly start a new paragraph. 81 if (Traits.isBlockCommand(Name)) { 82 // We found an implicit paragraph end. 83 InFirstParagraph = false; 84 if (InBrief) 85 break; 86 } 87 } 88 89 if (Tok.is(tok::newline)) { 90 if (InFirstParagraph || InBrief) 91 FirstParagraphOrBrief += ' '; 92 else if (InReturns) 93 ReturnsParagraph += ' '; 94 ConsumeToken(); 95 96 if (Tok.is(tok::newline)) { 97 ConsumeToken(); 98 // We found a paragraph end. 99 InFirstParagraph = false; 100 InReturns = false; 101 if (InBrief) 102 break; 103 } 104 continue; 105 } 106 107 // We didn't handle this token, so just drop it. 108 ConsumeToken(); 109 } 110 111 cleanupBrief(FirstParagraphOrBrief); 112 if (!FirstParagraphOrBrief.empty()) 113 return FirstParagraphOrBrief; 114 115 cleanupBrief(ReturnsParagraph); 116 return ReturnsParagraph; 117 } 118 119 } // end namespace comments 120 } // end namespace clang 121 122 123