blob: a56d79bda75e0ea7eccfd33107f3edb7c0640e0b [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)
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}
Dmitri Gribenkod558b522012-06-28 01:38:21 +000057} // unnamed namespace
58
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000059std::string BriefParser::Parse() {
Dmitri Gribenkoc0b83242012-06-27 01:17:34 +000060 std::string Paragraph;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000061 bool InFirstParagraph = true;
62 bool InBrief = false;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000063
64 while (Tok.isNot(tok::eof)) {
65 if (Tok.is(tok::text)) {
Dmitri Gribenkoc0b83242012-06-27 01:17:34 +000066 if (InFirstParagraph || InBrief)
67 Paragraph += 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();
74 if (Name == "brief") {
75 Paragraph.clear();
76 InBrief = true;
77 ConsumeToken();
78 continue;
79 }
Dmitri Gribenko55e18082012-06-29 18:19:20 +000080 // Block commands implicitly start a new paragraph.
81 if (isBlockCommand(Name)) {
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +000082 // We found an implicit paragraph end.
83 InFirstParagraph = false;
84 if (InBrief) {
85 InBrief = false;
86 break;
87 }
88 }
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000089 }
90
91 if (Tok.is(tok::newline)) {
Dmitri Gribenkoc0b83242012-06-27 01:17:34 +000092 if (InFirstParagraph || InBrief)
Dmitri Gribenkod558b522012-06-28 01:38:21 +000093 Paragraph += ' ';
Dmitri Gribenko2d44d772012-06-26 20:39:18 +000094 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;
Dmitri Gribenkof199b9c2012-06-28 00:01:41 +0000102 break;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000103 }
104 }
105 continue;
106 }
107
108 // We didn't handle this token, so just drop it.
109 ConsumeToken();
110 }
111
Dmitri Gribenkod558b522012-06-28 01:38:21 +0000112 cleanupBrief(Paragraph);
Dmitri Gribenkoc0b83242012-06-27 01:17:34 +0000113 return Paragraph;
Dmitri Gribenko2d44d772012-06-26 20:39:18 +0000114}
115
116BriefParser::BriefParser(Lexer &L) : L(L)
117{
118 // Get lookahead token.
119 ConsumeToken();
120}
121
122} // end namespace comments
123} // end namespace clang
124
125