blob: d94952ae1e8637ce024c04392f0cd164ecbf32d8 [file] [log] [blame]
//===--- Trivia.cpp - Swift Syntax Trivia Implementation ------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Syntax/RawSyntax.h"
#include "swift/Syntax/Trivia.h"
using namespace swift;
using namespace swift::syntax;
namespace {
void printRepeated(llvm::raw_ostream &OS, char c, size_t Count) {
for (decltype(Count) i = 0; i < Count; ++i)
OS << c;
}
void escapeNewlines(std::string &S) {
size_t Index = 0;
while (true) {
Index = S.find("\n", Index);
if (Index == std::string::npos)
break;
S.erase(Index, 1);
S.insert(Index, "\\n");
Index += 3;
}
}
} // end anonymous namespace
void TriviaPiece::dump(llvm::raw_ostream &OS, unsigned Indent) const {
printRepeated(OS, ' ', Indent);
OS << "(trivia ";
switch (Kind) {
case TriviaKind::Space:
OS << "space " << Count;
break;
case TriviaKind::Tab:
OS << "tab " << Count;
break;
case TriviaKind::VerticalTab:
OS << "vertical_tab " << Count;
break;
case TriviaKind::Formfeed:
OS << "form_feed " << Count;
break;
case TriviaKind::Newline:
OS << "newline " << Count;
break;
case TriviaKind::LineComment:
OS << "line_comment" << Text.str();
break;
case TriviaKind::BlockComment: {
// Make this fit a little more nicely with indentation
// and the lispy nature of the dump by escaping the newlines.
auto s = Text.str().str();
escapeNewlines(s);
OS << "block_comment" << Text.str();
break;
}
case TriviaKind::DocLineComment:
OS << "doc_line_comment" << Text.str();
break;
case TriviaKind::DocBlockComment: {
// Make this fit a little more nicely with indentation
// and the lispy nature of the dump by escaping the newlines.
auto s = Text.str().str();
escapeNewlines(s);
OS << "doc_block_comment" << Text.str();
break;
}
case TriviaKind::Backtick:
OS << "backtick " << Count;
break;
}
OS << ')';
}
void TriviaPiece::accumulateAbsolutePosition(AbsolutePosition &Pos) const {
switch (Kind) {
case TriviaKind::LineComment:
case TriviaKind::BlockComment:
case TriviaKind::DocBlockComment:
case TriviaKind::DocLineComment:
Pos.addText(Text.str());
break;
case TriviaKind::Newline:
Pos.addNewlines(Count);
break;
case TriviaKind::Space:
case TriviaKind::Backtick:
case TriviaKind::Tab:
case TriviaKind::VerticalTab:
case TriviaKind::Formfeed:
Pos.addColumns(Count);
break;
}
}
void TriviaPiece::print(llvm::raw_ostream &OS) const {
switch (Kind) {
case TriviaKind::Space:
printRepeated(OS, ' ', Count);
break;
case TriviaKind::Tab:
printRepeated(OS, '\t', Count);
break;
case TriviaKind::VerticalTab:
printRepeated(OS, '\v', Count);
break;
case TriviaKind::Formfeed:
printRepeated(OS, '\f', Count);
break;
case TriviaKind::Newline:
printRepeated(OS, '\n', Count);
break;
case TriviaKind::LineComment:
case TriviaKind::BlockComment:
case TriviaKind::DocLineComment:
case TriviaKind::DocBlockComment:
OS << Text.str();
break;
case TriviaKind::Backtick:
printRepeated(OS, '`', Count);
break;
}
}
#pragma mark - Trivia collection
Trivia Trivia::appending(const Trivia &Other) const {
auto NewPieces = Pieces;
std::copy(Other.begin(), Other.end(), std::back_inserter(NewPieces));
return { NewPieces };
}
void Trivia::dump(llvm::raw_ostream &OS, unsigned Indent) const {
for (const auto &Piece : Pieces) {
Piece.dump(OS, Indent);
}
}
void Trivia::dump() const {
dump(llvm::errs());
}
void Trivia::print(llvm::raw_ostream &OS) const {
for (const auto &Piece : Pieces) {
Piece.print(OS);
}
}
TriviaList::const_iterator Trivia::find(const TriviaKind DesiredKind) const {
return std::find_if(Pieces.begin(), Pieces.end(),
[=](const TriviaPiece &Piece) -> bool {
return Piece.Kind == DesiredKind;
});
}
Trivia Trivia::operator+(const Trivia &Other) const {
auto NewPieces = Pieces;
std::copy(Other.Pieces.begin(), Other.Pieces.end(),
std::back_inserter(NewPieces));
return { NewPieces };
}