forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			156 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
//===--- CommentBriefParser.cpp - Dumb comment parser ---------------------===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "clang/AST/CommentBriefParser.h"
 | 
						|
#include "clang/AST/CommentCommandTraits.h"
 | 
						|
#include "llvm/ADT/StringSwitch.h"
 | 
						|
 | 
						|
namespace clang {
 | 
						|
namespace comments {
 | 
						|
 | 
						|
namespace {
 | 
						|
inline bool isWhitespace(char C) {
 | 
						|
  return C == ' ' || C == '\n' || C == '\r' ||
 | 
						|
         C == '\t' || C == '\f' || C == '\v';
 | 
						|
}
 | 
						|
 | 
						|
/// Convert all whitespace into spaces, remove leading and trailing spaces,
 | 
						|
/// compress multiple spaces into one.
 | 
						|
void cleanupBrief(std::string &S) {
 | 
						|
  bool PrevWasSpace = true;
 | 
						|
  std::string::iterator O = S.begin();
 | 
						|
  for (std::string::iterator I = S.begin(), E = S.end();
 | 
						|
       I != E; ++I) {
 | 
						|
    const char C = *I;
 | 
						|
    if (isWhitespace(C)) {
 | 
						|
      if (!PrevWasSpace) {
 | 
						|
        *O++ = ' ';
 | 
						|
        PrevWasSpace = true;
 | 
						|
      }
 | 
						|
      continue;
 | 
						|
    } else {
 | 
						|
      *O++ = C;
 | 
						|
      PrevWasSpace = false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (O != S.begin() && *(O - 1) == ' ')
 | 
						|
    --O;
 | 
						|
 | 
						|
  S.resize(O - S.begin());
 | 
						|
}
 | 
						|
 | 
						|
bool isWhitespace(StringRef Text) {
 | 
						|
  for (StringRef::const_iterator I = Text.begin(), E = Text.end();
 | 
						|
       I != E; ++I) {
 | 
						|
    if (!isWhitespace(*I))
 | 
						|
      return false;
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
} // unnamed namespace
 | 
						|
 | 
						|
BriefParser::BriefParser(Lexer &L, const CommandTraits &Traits) :
 | 
						|
    L(L), Traits(Traits) {
 | 
						|
  // Get lookahead token.
 | 
						|
  ConsumeToken();
 | 
						|
}
 | 
						|
 | 
						|
std::string BriefParser::Parse() {
 | 
						|
  std::string FirstParagraphOrBrief;
 | 
						|
  std::string ReturnsParagraph;
 | 
						|
  bool InFirstParagraph = true;
 | 
						|
  bool InBrief = false;
 | 
						|
  bool InReturns = false;
 | 
						|
 | 
						|
  while (Tok.isNot(tok::eof)) {
 | 
						|
    if (Tok.is(tok::text)) {
 | 
						|
      if (InFirstParagraph || InBrief)
 | 
						|
        FirstParagraphOrBrief += Tok.getText();
 | 
						|
      else if (InReturns)
 | 
						|
        ReturnsParagraph += Tok.getText();
 | 
						|
      ConsumeToken();
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) {
 | 
						|
      const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID());
 | 
						|
      if (Info->IsBriefCommand) {
 | 
						|
        FirstParagraphOrBrief.clear();
 | 
						|
        InBrief = true;
 | 
						|
        ConsumeToken();
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      if (Info->IsReturnsCommand) {
 | 
						|
        InReturns = true;
 | 
						|
        InBrief = false;
 | 
						|
        InFirstParagraph = false;
 | 
						|
        ReturnsParagraph += "Returns ";
 | 
						|
        ConsumeToken();
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      // Block commands implicitly start a new paragraph.
 | 
						|
      if (Info->IsBlockCommand) {
 | 
						|
        // We found an implicit paragraph end.
 | 
						|
        InFirstParagraph = false;
 | 
						|
        if (InBrief)
 | 
						|
          break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (Tok.is(tok::newline)) {
 | 
						|
      if (InFirstParagraph || InBrief)
 | 
						|
        FirstParagraphOrBrief += ' ';
 | 
						|
      else if (InReturns)
 | 
						|
        ReturnsParagraph += ' ';
 | 
						|
      ConsumeToken();
 | 
						|
 | 
						|
      // If the next token is a whitespace only text, ignore it.  Thus we allow
 | 
						|
      // two paragraphs to be separated by line that has only whitespace in it.
 | 
						|
      //
 | 
						|
      // We don't need to add a space to the parsed text because we just added
 | 
						|
      // a space for the newline.
 | 
						|
      if (Tok.is(tok::text)) {
 | 
						|
        if (isWhitespace(Tok.getText()))
 | 
						|
          ConsumeToken();
 | 
						|
      }
 | 
						|
 | 
						|
      if (Tok.is(tok::newline)) {
 | 
						|
        ConsumeToken();
 | 
						|
        // We found a paragraph end.  This ends the brief description if
 | 
						|
        // \\brief command or its equivalent was explicitly used.
 | 
						|
        // Stop scanning text because an explicit \\brief paragraph is the
 | 
						|
        // preffered one.
 | 
						|
        if (InBrief)
 | 
						|
          break;
 | 
						|
        // End first paragraph if we found some non-whitespace text.
 | 
						|
        if (InFirstParagraph && !isWhitespace(FirstParagraphOrBrief))
 | 
						|
          InFirstParagraph = false;
 | 
						|
        // End the \\returns paragraph because we found the paragraph end.
 | 
						|
        InReturns = false;
 | 
						|
      }
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    // We didn't handle this token, so just drop it.
 | 
						|
    ConsumeToken();
 | 
						|
  }
 | 
						|
 | 
						|
  cleanupBrief(FirstParagraphOrBrief);
 | 
						|
  if (!FirstParagraphOrBrief.empty())
 | 
						|
    return FirstParagraphOrBrief;
 | 
						|
 | 
						|
  cleanupBrief(ReturnsParagraph);
 | 
						|
  return ReturnsParagraph;
 | 
						|
}
 | 
						|
 | 
						|
} // end namespace comments
 | 
						|
} // end namespace clang
 | 
						|
 | 
						|
 |