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