You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
4.2 KiB
155 lines
4.2 KiB
//===--- CommentBriefParser.cpp - Dumb comment parser ---------------------===// |
|
// |
|
// The LLVM Compiler Infrastructure |
|
// |
|
// This file is distributed under the University of Illinois Open Source |
|
// License. See LICENSE.TXT for details. |
|
// |
|
//===----------------------------------------------------------------------===// |
|
|
|
#include "clang/AST/CommentBriefParser.h" |
|
#include "clang/AST/CommentCommandTraits.h" |
|
#include "llvm/ADT/StringSwitch.h" |
|
|
|
namespace clang { |
|
namespace comments { |
|
|
|
namespace { |
|
inline bool isWhitespace(char C) { |
|
return C == ' ' || C == '\n' || C == '\r' || |
|
C == '\t' || C == '\f' || C == '\v'; |
|
} |
|
|
|
/// Convert all whitespace into spaces, remove leading and trailing spaces, |
|
/// compress multiple spaces into one. |
|
void cleanupBrief(std::string &S) { |
|
bool PrevWasSpace = true; |
|
std::string::iterator O = S.begin(); |
|
for (std::string::iterator I = S.begin(), E = S.end(); |
|
I != E; ++I) { |
|
const char C = *I; |
|
if (isWhitespace(C)) { |
|
if (!PrevWasSpace) { |
|
*O++ = ' '; |
|
PrevWasSpace = true; |
|
} |
|
continue; |
|
} else { |
|
*O++ = C; |
|
PrevWasSpace = false; |
|
} |
|
} |
|
if (O != S.begin() && *(O - 1) == ' ') |
|
--O; |
|
|
|
S.resize(O - S.begin()); |
|
} |
|
|
|
bool isWhitespace(StringRef Text) { |
|
for (StringRef::const_iterator I = Text.begin(), E = Text.end(); |
|
I != E; ++I) { |
|
if (!isWhitespace(*I)) |
|
return false; |
|
} |
|
return true; |
|
} |
|
} // unnamed namespace |
|
|
|
BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) : |
|
L(L), Traits(Traits) { |
|
// Get lookahead token. |
|
ConsumeToken(); |
|
} |
|
|
|
std::string BriefParser::Parse() { |
|
std::string FirstParagraphOrBrief; |
|
std::string ReturnsParagraph; |
|
bool InFirstParagraph = true; |
|
bool InBrief = false; |
|
bool InReturns = false; |
|
|
|
while (Tok.isNot(tok::eof)) { |
|
if (Tok.is(tok::text)) { |
|
if (InFirstParagraph || InBrief) |
|
FirstParagraphOrBrief += Tok.getText(); |
|
else if (InReturns) |
|
ReturnsParagraph += Tok.getText(); |
|
ConsumeToken(); |
|
continue; |
|
} |
|
|
|
if (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) { |
|
const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); |
|
if (Info->IsBriefCommand) { |
|
FirstParagraphOrBrief.clear(); |
|
InBrief = true; |
|
ConsumeToken(); |
|
continue; |
|
} |
|
if (Info->IsReturnsCommand) { |
|
InReturns = true; |
|
InBrief = false; |
|
InFirstParagraph = false; |
|
ReturnsParagraph += "Returns "; |
|
ConsumeToken(); |
|
continue; |
|
} |
|
// Block commands implicitly start a new paragraph. |
|
if (Info->IsBlockCommand) { |
|
// We found an implicit paragraph end. |
|
InFirstParagraph = false; |
|
if (InBrief) |
|
break; |
|
} |
|
} |
|
|
|
if (Tok.is(tok::newline)) { |
|
if (InFirstParagraph || InBrief) |
|
FirstParagraphOrBrief += ' '; |
|
else if (InReturns) |
|
ReturnsParagraph += ' '; |
|
ConsumeToken(); |
|
|
|
// If the next token is a whitespace only text, ignore it. Thus we allow |
|
// two paragraphs to be separated by line that has only whitespace in it. |
|
// |
|
// We don't need to add a space to the parsed text because we just added |
|
// a space for the newline. |
|
if (Tok.is(tok::text)) { |
|
if (isWhitespace(Tok.getText())) |
|
ConsumeToken(); |
|
} |
|
|
|
if (Tok.is(tok::newline)) { |
|
ConsumeToken(); |
|
// We found a paragraph end. This ends the brief description if |
|
// \\brief command or its equivalent was explicitly used. |
|
// Stop scanning text because an explicit \\brief paragraph is the |
|
// preffered one. |
|
if (InBrief) |
|
break; |
|
// End first paragraph if we found some non-whitespace text. |
|
if (InFirstParagraph && !isWhitespace(FirstParagraphOrBrief)) |
|
InFirstParagraph = false; |
|
// End the \\returns paragraph because we found the paragraph end. |
|
InReturns = false; |
|
} |
|
continue; |
|
} |
|
|
|
// We didn't handle this token, so just drop it. |
|
ConsumeToken(); |
|
} |
|
|
|
cleanupBrief(FirstParagraphOrBrief); |
|
if (!FirstParagraphOrBrief.empty()) |
|
return FirstParagraphOrBrief; |
|
|
|
cleanupBrief(ReturnsParagraph); |
|
return ReturnsParagraph; |
|
} |
|
|
|
} // end namespace comments |
|
} // end namespace clang |
|
|
|
|
|
|