//===--- UnwrappedLineParser.cpp - Format C++ code ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file contains the implementation of the UnwrappedLineParser,
/// which turns a stream of tokens into UnwrappedLines.
///
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "format-parser"
#include "UnwrappedLineParser.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Debug.h"
namespace clang {
namespace format {
class ScopedDeclarationState {
public:
ScopedDeclarationState(UnwrappedLine &Line, std::vector<bool> &Stack,
bool MustBeDeclaration)
: Line(Line), Stack(Stack) {
Line.MustBeDeclaration = MustBeDeclaration;
Stack.push_back(MustBeDeclaration);
}
~ScopedDeclarationState() {
Stack.pop_back();
if (!Stack.empty())
Line.MustBeDeclaration = Stack.back();
else
Line.MustBeDeclaration = true;
}
private:
UnwrappedLine &Line;
std::vector<bool> &Stack;
};
class ScopedMacroState : public FormatTokenSource {
public:
ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
FormatToken &ResetToken, bool &StructuralError)
: Line(Line), TokenSource(TokenSource), ResetToken(ResetToken),
PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource),
StructuralError(StructuralError),
PreviousStructuralError(StructuralError) {
TokenSource = this;
Line.Level = 0;
Line.InPPDirective = true;
}
~ScopedMacroState() {
TokenSource = PreviousTokenSource;
ResetToken = Token;
Line.InPPDirective = false;
Line.Level = PreviousLineLevel;
StructuralError = PreviousStructuralError;
}
virtual FormatToken getNextToken() {
// The \c UnwrappedLineParser guards against this by never calling
// \c getNextToken() after it has encountered the first eof token.
assert(!eof());
Token = PreviousTokenSource->getNextToken();
if (eof())
return createEOF();
return Token;
}
private:
bool eof() { return Token.HasUnescapedNewline; }
FormatToken createEOF() {
FormatToken FormatTok;
FormatTok.Tok.startToken();
FormatTok.Tok.setKind(tok::eof);
return FormatTok;
}
UnwrappedLine &Line;
FormatTokenSource *&TokenSource;
FormatToken &ResetToken;
unsigned PreviousLineLevel;
FormatTokenSource *PreviousTokenSource;
bool &StructuralError;
bool PreviousStructuralError;
FormatToken Token;
};
class ScopedLineState {
public:
ScopedLineState(UnwrappedLineParser &Parser,
bool SwitchToPreprocessorLines = false)
: Parser(Parser), SwitchToPreprocessorLines(SwitchToPreprocessorLines) {
if (SwitchToPreprocessorLines)
Parser.CurrentLines = &Parser.PreprocessorDirectives;
PreBlockLine = Parser.Line.take();
Parser.Line.reset(new UnwrappedLine());
Parser.Line->Level = PreBlockLine->Level;
Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
}
~ScopedLineState() {
if (!Parser.Line->Tokens.empty()) {
Parser.addUnwrappedLine();
}
assert(Parser.Line->Tokens.empty());
Parser.Line.reset(PreBlockLine);
Parser.MustBreakBeforeNextToken = true;
if (SwitchToPreprocessorLines)
Parser.CurrentLines = &Parser.Lines;
}
private:
UnwrappedLineParser &Parser;
const bool SwitchToPreprocessorLines;
UnwrappedLine *PreBlockLine;
};
UnwrappedLineParser::UnwrappedLineParser(
clang::DiagnosticsEngine &Diag, const FormatStyle &Style,
FormatTokenSource &Tokens, UnwrappedLineConsumer &Callback)
: Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
CurrentLines(&Lines), StructuralError(false), Diag(Diag), Style(Style),
Tokens(&Tokens), Callback(Callback) {}
bool UnwrappedLineParser::parse() {
DEBUG(llvm::dbgs() << "----\n");
readToken();
parseFile();
for (std::vector<UnwrappedLine>::iterator I = Lines.begin(), E = Lines.end();
I != E; ++I) {
Callback.consumeUnwrappedLine(*I);
}
// Create line with eof token.
pushToken(FormatTok);
Callback.consumeUnwrappedLine(*Line);
return StructuralError;
}
void UnwrappedLineParser::parseFile() {
ScopedDeclarationState DeclarationState(
*Line, DeclarationScopeStack,
/*MustBeDeclaration=*/ !Line->InPPDirective);
parseLevel(/*HasOpeningBrace=*/ false);
// Make sure to format the remaining tokens.
flushComments(true);
addUnwrappedLine();
}
void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
do