llvm-project
142 строки · 4.0 Кб
1//===--- CommentBriefParser.cpp - Dumb comment parser ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/AST/CommentBriefParser.h"10#include "clang/AST/CommentCommandTraits.h"11#include "clang/Basic/CharInfo.h"12
13namespace clang {14namespace comments {15
16namespace {17
18/// Convert all whitespace into spaces, remove leading and trailing spaces,
19/// compress multiple spaces into one.
20void cleanupBrief(std::string &S) {21bool PrevWasSpace = true;22std::string::iterator O = S.begin();23for (std::string::iterator I = S.begin(), E = S.end();24I != E; ++I) {25const char C = *I;26if (clang::isWhitespace(C)) {27if (!PrevWasSpace) {28*O++ = ' ';29PrevWasSpace = true;30}31} else {32*O++ = C;33PrevWasSpace = false;34}35}36if (O != S.begin() && *(O - 1) == ' ')37--O;38
39S.resize(O - S.begin());40}
41
42bool isWhitespace(StringRef Text) {43return llvm::all_of(Text, clang::isWhitespace);44}
45} // unnamed namespace46
47BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) :48L(L), Traits(Traits) {49// Get lookahead token.50ConsumeToken();51}
52
53std::string BriefParser::Parse() {54std::string FirstParagraphOrBrief;55std::string ReturnsParagraph;56bool InFirstParagraph = true;57bool InBrief = false;58bool InReturns = false;59
60while (Tok.isNot(tok::eof)) {61if (Tok.is(tok::text)) {62if (InFirstParagraph || InBrief)63FirstParagraphOrBrief += Tok.getText();64else if (InReturns)65ReturnsParagraph += Tok.getText();66ConsumeToken();67continue;68}69
70if (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) {71const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());72if (Info->IsBriefCommand) {73FirstParagraphOrBrief.clear();74InBrief = true;75ConsumeToken();76continue;77}78if (Info->IsReturnsCommand) {79InReturns = true;80InBrief = false;81InFirstParagraph = false;82ReturnsParagraph += "Returns ";83ConsumeToken();84continue;85}86// Block commands implicitly start a new paragraph.87if (Info->IsBlockCommand) {88// We found an implicit paragraph end.89InFirstParagraph = false;90if (InBrief)91break;92}93}94
95if (Tok.is(tok::newline)) {96if (InFirstParagraph || InBrief)97FirstParagraphOrBrief += ' ';98else if (InReturns)99ReturnsParagraph += ' ';100ConsumeToken();101
102// If the next token is a whitespace only text, ignore it. Thus we allow103// two paragraphs to be separated by line that has only whitespace in it.104//105// We don't need to add a space to the parsed text because we just added106// a space for the newline.107if (Tok.is(tok::text)) {108if (isWhitespace(Tok.getText()))109ConsumeToken();110}111
112if (Tok.is(tok::newline)) {113ConsumeToken();114// We found a paragraph end. This ends the brief description if115// \command or its equivalent was explicitly used.116// Stop scanning text because an explicit \paragraph is the117// preferred one.118if (InBrief)119break;120// End first paragraph if we found some non-whitespace text.121if (InFirstParagraph && !isWhitespace(FirstParagraphOrBrief))122InFirstParagraph = false;123// End the \\returns paragraph because we found the paragraph end.124InReturns = false;125}126continue;127}128
129// We didn't handle this token, so just drop it.130ConsumeToken();131}132
133cleanupBrief(FirstParagraphOrBrief);134if (!FirstParagraphOrBrief.empty())135return FirstParagraphOrBrief;136
137cleanupBrief(ReturnsParagraph);138return ReturnsParagraph;139}
140
141} // end namespace comments142} // end namespace clang143
144
145