blob: 47d52e19a2d3628baaa4b3f15466ba3bd5e48090 [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 Gribenko55e18082012-06-29 18:19:20 +000051 .Default(false);
52}
Dmitri Gribenkod558b522012-06-28 01:38:21 +000053} // unnamed namespace
54
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000055std::string BriefParser::Parse() {
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000056 std::string FirstParagraphOrBrief;
57 std::string ReturnsParagraph;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000058 bool InFirstParagraph = true;
59 bool InBrief = false;
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000060 bool InReturns = false;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000061
62 while (Tok.isNot(tok::eof)) {
63 if (Tok.is(tok::text)) {
Dmitri Gribenkoc0b83242012-06-27 01:17:34 +000064 if (InFirstParagraph || InBrief)
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000065 FirstParagraphOrBrief += Tok.getText();
66 else if (InReturns)
67 ReturnsParagraph += Tok.getText();
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000068 ConsumeToken();
69 continue;
70 }
71
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000072 if (Tok.is(tok::command)) {
73 StringRef Name = Tok.getCommandName();
Dmitri Gribenko659a7122012-07-17 18:35:14 +000074 if (Name == "brief" || Name == "short") {
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000075 FirstParagraphOrBrief.clear();
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000076 InBrief = true;
77 ConsumeToken();
78 continue;
79 }
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000080 if (Name == "result" || Name == "return" || Name == "returns") {
81 InReturns = true;
82 ReturnsParagraph += "Returns ";
83 }
Dmitri Gribenko55e18082012-06-29 18:19:20 +000084 // Block commands implicitly start a new paragraph.
85 if (isBlockCommand(Name)) {
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000086 // We found an implicit paragraph end.
87 InFirstParagraph = false;
Dmitri Gribenko57aceb22012-07-03 18:10:20 +000088 if (InBrief)
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000089 break;
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000090 }
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000091 }
92
93 if (Tok.is(tok::newline)) {
Dmitri Gribenkoc0b83242012-06-27 01:17:34 +000094 if (InFirstParagraph || InBrief)
Dmitri Gribenko72021ff2012-07-20 17:01:34 +000095 FirstParagraphOrBrief += ' ';
96 else if (InReturns)
97 ReturnsParagraph += ' ';
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000098 ConsumeToken();
99
100 if (Tok.is(tok::newline)) {
101 ConsumeToken();
102 // We found a paragraph end.
103 InFirstParagraph = false;
Dmitri Gribenko72021ff2012-07-20 17:01:34 +0000104 InReturns = false;
Dmitri Gribenko57aceb22012-07-03 18:10:20 +0000105 if (InBrief)
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +0000106 break;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000107 }
108 continue;
109 }
110
111 // We didn't handle this token, so just drop it.
112 ConsumeToken();
113 }
114
Dmitri Gribenko72021ff2012-07-20 17:01:34 +0000115 cleanupBrief(FirstParagraphOrBrief);
116 if (!FirstParagraphOrBrief.empty())
117 return FirstParagraphOrBrief;
118
119 cleanupBrief(ReturnsParagraph);
120 return ReturnsParagraph;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000121}
122
Dmitri Gribenko4423f812012-07-20 17:02:25 +0000123BriefParser::BriefParser(Lexer &L) : L(L) {
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000124 // Get lookahead token.
125 ConsumeToken();
126}
127
128} // end namespace comments
129} // end namespace clang
130
131