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           InBrief = false;
86           break;
87         }
88       }
89     }
90 
91     if (Tok.is(tok::newline)) {
92       if (InFirstParagraph || InBrief)
93         Paragraph += ' ';
94       ConsumeToken();
95 
96       if (Tok.is(tok::newline)) {
97         ConsumeToken();
98         // We found a paragraph end.
99         InFirstParagraph = false;
100         if (InBrief) {
101           InBrief = false;
102           break;
103         }
104       }
105       continue;
106     }
107 
108     // We didn't handle this token, so just drop it.
109     ConsumeToken();
110   }
111 
112   cleanupBrief(Paragraph);
113   return Paragraph;
114 }
115 
116 BriefParser::BriefParser(Lexer &L) : L(L)
117 {
118   // Get lookahead token.
119   ConsumeToken();
120 }
121 
122 } // end namespace comments
123 } // end namespace clang
124 
125 
126