clang  3.7.0
CommentBriefParser.cpp
Go to the documentation of this file.
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 
12 #include "llvm/ADT/StringSwitch.h"
13 
14 namespace clang {
15 namespace comments {
16 
17 namespace {
18 inline bool isWhitespace(char C) {
19  return C == ' ' || C == '\n' || C == '\r' ||
20  C == '\t' || C == '\f' || C == '\v';
21 }
22 
23 /// Convert all whitespace into spaces, remove leading and trailing spaces,
24 /// compress multiple spaces into one.
25 void cleanupBrief(std::string &S) {
26  bool PrevWasSpace = true;
27  std::string::iterator O = S.begin();
28  for (std::string::iterator I = S.begin(), E = S.end();
29  I != E; ++I) {
30  const char C = *I;
31  if (isWhitespace(C)) {
32  if (!PrevWasSpace) {
33  *O++ = ' ';
34  PrevWasSpace = true;
35  }
36  continue;
37  } else {
38  *O++ = C;
39  PrevWasSpace = false;
40  }
41  }
42  if (O != S.begin() && *(O - 1) == ' ')
43  --O;
44 
45  S.resize(O - S.begin());
46 }
47 
48 bool isWhitespace(StringRef Text) {
49  for (StringRef::const_iterator I = Text.begin(), E = Text.end();
50  I != E; ++I) {
51  if (!isWhitespace(*I))
52  return false;
53  }
54  return true;
55 }
56 } // unnamed namespace
57 
59  L(L), Traits(Traits) {
60  // Get lookahead token.
61  ConsumeToken();
62 }
63 
64 std::string BriefParser::Parse() {
65  std::string FirstParagraphOrBrief;
66  std::string ReturnsParagraph;
67  bool InFirstParagraph = true;
68  bool InBrief = false;
69  bool InReturns = false;
70 
71  while (Tok.isNot(tok::eof)) {
72  if (Tok.is(tok::text)) {
73  if (InFirstParagraph || InBrief)
74  FirstParagraphOrBrief += Tok.getText();
75  else if (InReturns)
76  ReturnsParagraph += Tok.getText();
77  ConsumeToken();
78  continue;
79  }
80 
81  if (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) {
82  const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
83  if (Info->IsBriefCommand) {
84  FirstParagraphOrBrief.clear();
85  InBrief = true;
86  ConsumeToken();
87  continue;
88  }
89  if (Info->IsReturnsCommand) {
90  InReturns = true;
91  InBrief = false;
92  InFirstParagraph = false;
93  ReturnsParagraph += "Returns ";
94  ConsumeToken();
95  continue;
96  }
97  // Block commands implicitly start a new paragraph.
98  if (Info->IsBlockCommand) {
99  // We found an implicit paragraph end.
100  InFirstParagraph = false;
101  if (InBrief)
102  break;
103  }
104  }
105 
106  if (Tok.is(tok::newline)) {
107  if (InFirstParagraph || InBrief)
108  FirstParagraphOrBrief += ' ';
109  else if (InReturns)
110  ReturnsParagraph += ' ';
111  ConsumeToken();
112 
113  // If the next token is a whitespace only text, ignore it. Thus we allow
114  // two paragraphs to be separated by line that has only whitespace in it.
115  //
116  // We don't need to add a space to the parsed text because we just added
117  // a space for the newline.
118  if (Tok.is(tok::text)) {
119  if (isWhitespace(Tok.getText()))
120  ConsumeToken();
121  }
122 
123  if (Tok.is(tok::newline)) {
124  ConsumeToken();
125  // We found a paragraph end. This ends the brief description if
126  // \\brief command or its equivalent was explicitly used.
127  // Stop scanning text because an explicit \\brief paragraph is the
128  // preffered one.
129  if (InBrief)
130  break;
131  // End first paragraph if we found some non-whitespace text.
132  if (InFirstParagraph && !isWhitespace(FirstParagraphOrBrief))
133  InFirstParagraph = false;
134  // End the \\returns paragraph because we found the paragraph end.
135  InReturns = false;
136  }
137  continue;
138  }
139 
140  // We didn't handle this token, so just drop it.
141  ConsumeToken();
142  }
143 
144  cleanupBrief(FirstParagraphOrBrief);
145  if (!FirstParagraphOrBrief.empty())
146  return FirstParagraphOrBrief;
147 
148  cleanupBrief(ReturnsParagraph);
149  return ReturnsParagraph;
150 }
151 
152 } // end namespace comments
153 } // end namespace clang
154 
155 
static LLVM_READONLY bool isWhitespace(unsigned char c)
Definition: CharInfo.h:88
Information about a single command.
const CommandInfo * getCommandInfo(StringRef Name) const
bool isNot(tok::TokenKind K) const LLVM_READONLY
Definition: CommentLexer.h:95
bool is(tok::TokenKind K) const LLVM_READONLY
Definition: CommentLexer.h:94
Comment lexer.
Definition: CommentLexer.h:222
std::string Parse()
Return the best "brief description" we can find.
unsigned getCommandID() const LLVM_READONLY
Definition: CommentLexer.h:122
unsigned IsBlockCommand
True if this command is a block command (of any kind).
unsigned IsReturnsCommand
True if this command is \returns or an alias.
StringRef getText() const LLVM_READONLY
Definition: CommentLexer.h:100
BriefParser(Lexer &L, const CommandTraits &Traits)