blob: 22209c097fd3f448553f229a6ec5d7602c373903 [file] [log] [blame]
Dmitri Gribenko2d44d772012-06-26 20:39:18 +00001//===--- 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"
Dmitri Gribenko55e18082012-06-29 18:19:20 +000011#include "llvm/ADT/StringSwitch.h"
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000012
13namespace clang {
14namespace comments {
15
Dmitri Gribenkod558b522012-06-28 01:38:21 +000016namespace {
17/// Convert all whitespace into spaces, remove leading and trailing spaces,
18/// compress multiple spaces into one.
19void cleanupBrief(std::string &S) {
20 bool PrevWasSpace = true;
21 std::string::iterator O = S.begin();
22 for (std::string::iterator I = S.begin(), E = S.end();
23 I != E; ++I) {
24 const char C = *I;
25 if (C == ' ' || C == '\n' || C == '\r' ||
26 C == '\t' || C == '\v' || C == '\f') {
27 if (!PrevWasSpace) {
28 *O++ = ' ';
29 PrevWasSpace = true;
30 }
31 continue;
32 } else {
33 *O++ = C;
34 PrevWasSpace = false;
35 }
36 }
37 if (O != S.begin() && *(O - 1) == ' ')
38 --O;
39
40 S.resize(O - S.begin());
41}
Dmitri Gribenko55e18082012-06-29 18:19:20 +000042
43bool isBlockCommand(StringRef Name) {
44 return llvm::StringSwitch<bool>(Name)
Dmitri Gribenko76e7edd2012-07-17 21:21:55 +000045 .Cases("brief", "short", true)
46 .Cases("result", "return", "returns", true)
47 .Cases("author", "authors", true)
Dmitri Gribenko55e18082012-06-29 18:19:20 +000048 .Case("pre", true)
49 .Case("post", true)
Dmitri Gribenko76e7edd2012-07-17 21:21:55 +000050 .Cases("param", "arg", true)
Dmitri Gribenko96b09862012-07-31 22:37:06 +000051 .Case("tparam", true)
Dmitri Gribenko55e18082012-06-29 18:19:20 +000052 .Default(false);
53}
Dmitri Gribenkod558b522012-06-28 01:38:21 +000054} // unnamed namespace
55
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000056std::string BriefParser::Parse() {
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000057 std::string FirstParagraphOrBrief;
58 std::string ReturnsParagraph;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000059 bool InFirstParagraph = true;
60 bool InBrief = false;
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000061 bool InReturns = false;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000062
63 while (Tok.isNot(tok::eof)) {
64 if (Tok.is(tok::text)) {
Dmitri Gribenkoc0b83242012-06-27 01:17:34 +000065 if (InFirstParagraph || InBrief)
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000066 FirstParagraphOrBrief += Tok.getText();
67 else if (InReturns)
68 ReturnsParagraph += Tok.getText();
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000069 ConsumeToken();
70 continue;
71 }
72
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000073 if (Tok.is(tok::command)) {
74 StringRef Name = Tok.getCommandName();
Dmitri Gribenko659a7122012-07-17 18:35:14 +000075 if (Name == "brief" || Name == "short") {
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000076 FirstParagraphOrBrief.clear();
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000077 InBrief = true;
78 ConsumeToken();
79 continue;
80 }
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000081 if (Name == "result" || Name == "return" || Name == "returns") {
82 InReturns = true;
83 ReturnsParagraph += "Returns ";
84 }
Dmitri Gribenko55e18082012-06-29 18:19:20 +000085 // Block commands implicitly start a new paragraph.
86 if (isBlockCommand(Name)) {
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000087 // We found an implicit paragraph end.
88 InFirstParagraph = false;
Dmitri Gribenko57aceb22012-07-03 18:10:20 +000089 if (InBrief)
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000090 break;
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000091 }
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000092 }
93
94 if (Tok.is(tok::newline)) {
Dmitri Gribenkoc0b83242012-06-27 01:17:34 +000095 if (InFirstParagraph || InBrief)
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000096 FirstParagraphOrBrief += ' ';
97 else if (InReturns)
98 ReturnsParagraph += ' ';
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000099 ConsumeToken();
100
101 if (Tok.is(tok::newline)) {
102 ConsumeToken();
103 // We found a paragraph end.
104 InFirstParagraph = false;
Dmitri Gribenko72021ff2012-07-20 17:01:34 +0000105 InReturns = false;
Dmitri Gribenko57aceb22012-07-03 18:10:20 +0000106 if (InBrief)
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +0000107 break;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000108 }
109 continue;
110 }
111
112 // We didn't handle this token, so just drop it.
113 ConsumeToken();
114 }
115
Dmitri Gribenko72021ff2012-07-20 17:01:34 +0000116 cleanupBrief(FirstParagraphOrBrief);
117 if (!FirstParagraphOrBrief.empty())
118 return FirstParagraphOrBrief;
119
120 cleanupBrief(ReturnsParagraph);
121 return ReturnsParagraph;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000122}
123
Dmitri Gribenko4423f812012-07-20 17:02:25 +0000124BriefParser::BriefParser(Lexer &L) : L(L) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000125 // Get lookahead token.
126 ConsumeToken();
127}
128
129} // end namespace comments
130} // end namespace clang
131
132