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 
10 #include "clang/AST/CommentBriefParser.h"
11 #include "llvm/ADT/StringSwitch.h"
12 
13 namespace clang {
14 namespace comments {
15 
16 namespace {
17 /// Convert all whitespace into spaces, remove leading and trailing spaces,
18 /// compress multiple spaces into one.
19 void 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 }
42 
43 bool isBlockCommand(StringRef Name) {
44   return llvm::StringSwitch<bool>(Name)
45       .Case("brief", true)
46       .Case("result", true)
47       .Case("return", true)
48       .Case("returns", true)
49       .Case("author", true)
50       .Case("authors", true)
51       .Case("pre", true)
52       .Case("post", true)
53       .Case("param", true)
54       .Case("arg", true)
55       .Default(false);
56 }
57 } // unnamed namespace
58 
59 std::string BriefParser::Parse() {
60   std::string Paragraph;
61   bool InFirstParagraph = true;
62   bool InBrief = false;
63 
64   while (Tok.isNot(tok::eof)) {
65     if (Tok.is(tok::text)) {
66       if (InFirstParagraph || InBrief)
67         Paragraph += Tok.getText();
68       ConsumeToken();
69       continue;
70     }
71 
72     if (Tok.is(tok::command)) {
73       StringRef Name = Tok.getCommandName();
74       if (Name == "brief") {
75         Paragraph.clear();
76         InBrief = true;
77         ConsumeToken();
78         continue;
79       }
80       // Block commands implicitly start a new paragraph.
81       if (isBlockCommand(Name)) {
82         // We found an implicit paragraph end.
83         InFirstParagraph = false;
84         if (InBrief)
85           break;
86       }
87     }
88 
89     if (Tok.is(tok::newline)) {
90       if (InFirstParagraph || InBrief)
91         Paragraph += ' ';
92       ConsumeToken();
93 
94       if (Tok.is(tok::newline)) {
95         ConsumeToken();
96         // We found a paragraph end.
97         InFirstParagraph = false;
98         if (InBrief)
99           break;
100       }
101       continue;
102     }
103 
104     // We didn't handle this token, so just drop it.
105     ConsumeToken();
106   }
107 
108   cleanupBrief(Paragraph);
109   return Paragraph;
110 }
111 
112 BriefParser::BriefParser(Lexer &L) : L(L)
113 {
114   // Get lookahead token.
115   ConsumeToken();
116 }
117 
118 } // end namespace comments
119 } // end namespace clang
120 
121 
122