#include "clang/AST/CommentLexer.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
namespace comments {
void Token::dump(const Lexer &L, const SourceManager &SM) const {
llvm::errs() << "comments::Token Kind=" << Kind << " ";
Loc.dump(SM);
llvm::errs() << " " << Length << " \"" << L.getSpelling(*this, SM) << "\"\n";
}
bool Lexer::isVerbatimBlockCommand(StringRef BeginName,
StringRef &EndName) const {
const char *Result = llvm::StringSwitch<const char *>(BeginName)
.Case("code", "endcode")
.Case("verbatim", "endverbatim")
.Case("htmlonly", "endhtmlonly")
.Case("latexonly", "endlatexonly")
.Case("xmlonly", "endxmlonly")
.Case("manonly", "endmanonly")
.Case("rtfonly", "endrtfonly")
.Case("dot", "enddot")
.Case("msc", "endmsc")
.Case("f$", "f$") // Inline LaTeX formula
.Case("f[", "f]") // Displayed LaTeX formula
.Case("f{", "f}") // LaTeX environment
.Default(NULL);
if (Result) {
EndName = Result;
return true;
}
for (VerbatimBlockCommandVector::const_iterator
I = VerbatimBlockCommands.begin(),
E = VerbatimBlockCommands.end();
I != E; ++I)
if (I->BeginName == BeginName) {
EndName = I->EndName;
return true;
}
return false;
}
bool Lexer::isVerbatimLineCommand(StringRef Name) const {
bool Result = llvm::StringSwitch<bool>(Name)
.Case("fn", true)
.Case("var", true)
.Case("property", true)
.Case("typedef", true)
.Case("overload", true)
.Case("defgroup", true)
.Case("ingroup", true)
.Case("addtogroup", true)
.Case("weakgroup", true)
.Case("name", true)
.Case("section", true)
.Case("subsection", true)
.Case("subsubsection", true)
.Case("paragraph", true)
.Case("mainpage", true)
.Case("subpage", true)
.Case("ref", true)
.Default(false);
if (Result)
return true;
for (VerbatimLineCommandVector::const_iterator
I = VerbatimLineCommands.begin(),
E = VerbatimLineCommands.end();
I != E; ++I)
if (I->Name == Name)
return true;
return false;
}
void Lexer::skipLineStartingDecorations() {
// This function should be called only for C comments
assert(CommentState == LCS_InsideCComment);
if (BufferPtr == CommentEnd)
return;
switch (*BufferPtr) {
case ' ':
case '\t':
case '\f':
case '\v': {
const char *NewBufferPtr = BufferPtr;
NewBufferPtr++;
if (NewBufferPtr == CommentEnd)
return;
char C = *NewBufferPtr;
while (C == ' ' || C == '\t' || C == '\f' || C == '\v') {
NewBufferPtr++;
if (NewBufferPtr == CommentEnd)
return;
C = *NewBufferPtr;
}
if (C == '*')
BufferPtr = NewBufferPtr + 1;
break;
}
case '*':
BufferPtr++;
break;
}
}
namespace {
/// Returns pointer to the first newline character in the string.
const char *findNewline(const char *BufferPtr, const char *BufferEnd) {
for ( ; BufferPtr != BufferEnd; ++BufferPtr) {
const char C = *BufferPtr;
if (C == '\n' || C == '\r')
return BufferPtr;
}
return BufferEnd;
}
const char *skipNewline(const char *BufferPtr, const char *BufferEnd) {
if (BufferPtr == BufferEnd)
return BufferPtr;
if (*BufferPtr == '\n')
BufferPtr++;
else {
assert(*BufferPtr == '\r');
BufferPtr++;
if (BufferPtr != BufferEnd && *BufferPtr == '\n')
BufferPtr++;
}
return BufferPtr;
}
bool isHTMLIdentifierStartingCharacter(char C) {
return (C >= 'a' && C <= 'z') ||
(C >= 'A' && C <= 'Z');
}
bool isHTMLIdentifierCharacter(char C) {
return (C >= 'a' && C <= 'z') ||
(C >= 'A' && C <= 'Z') ||
(C >= '0' && C <= '9');
}
const char *skipHTMLIdentifier(const char *BufferPtr, const char *BufferEnd) {
for ( ; BufferPtr != BufferEnd; ++BufferPtr) {