//===--- 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 }; }