llvm-project
130 строк · 3.6 Кб
1//===--- Token.cpp - Tokens and token streams in the pseudoparser ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang-pseudo/Token.h"10#include "clang/Basic/LangOptions.h"11#include "llvm/ADT/StringExtras.h"12#include "llvm/Support/Format.h"13#include "llvm/Support/FormatVariadic.h"14
15namespace clang {16namespace pseudo {17
18llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Token &T) {19OS << llvm::formatv("{0} {1}:{2} ", clang::tok::getTokenName(T.Kind), T.Line,20T.Indent);21OS << '"';22llvm::printEscapedString(T.text(), OS);23OS << '"';24if (T.Flags)25OS << llvm::format(" flags=%x", T.Flags);26return OS;27}
28
29llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TokenStream &TS) {30OS << "Index Kind Line Text\n";31for (const auto &T : TS.tokens()) {32OS << llvm::format("%5d: %16s %4d:%-2d ", TS.index(T),33clang::tok::getTokenName(T.Kind), T.Line, T.Indent);34OS << '"';35llvm::printEscapedString(T.text(), OS);36OS << '"';37if (T.Flags)38OS << llvm::format(" flags=%x", T.Flags);39OS << '\n';40}41return OS;42}
43
44llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Token::Range &R) {45OS << llvm::formatv("[{0},{1})", R.Begin, R.End);46return OS;47}
48
49TokenStream::TokenStream(std::shared_ptr<void> Payload)50: Payload(std::move(Payload)) {51Storage.emplace_back();52Storage.back().Kind = clang::tok::eof;53}
54
55void TokenStream::finalize() {56assert(!isFinalized());57unsigned LastLine = Storage.back().Line;58Storage.emplace_back();59Storage.back().Kind = tok::eof;60Storage.back().Line = LastLine + 1;61
62Tokens = Storage;63Tokens = Tokens.drop_front().drop_back();64}
65
66bool TokenStream::isFinalized() const {67assert(!Storage.empty() && Storage.front().Kind == tok::eof);68if (Storage.size() == 1)69return false;70return Storage.back().Kind == tok::eof;71}
72
73void TokenStream::print(llvm::raw_ostream &OS) const {74bool FirstToken = true;75unsigned LastLine = -1;76StringRef LastText;77for (const auto &T : tokens()) {78StringRef Text = T.text();79if (FirstToken) {80FirstToken = false;81} else if (T.Line == LastLine) {82if (LastText.data() + LastText.size() != Text.data())83OS << ' ';84} else {85OS << '\n';86OS.indent(T.Indent);87}88OS << Text;89LastLine = T.Line;90LastText = Text;91}92if (!FirstToken)93OS << '\n';94}
95
96clang::LangOptions genericLangOpts(clang::Language Lang,97clang::LangStandard::Kind Standard) {98clang::LangOptions Opts;99std::vector<std::string> UnusedIncludes;100LangOptions::setLangDefaults(Opts, Lang, llvm::Triple(), UnusedIncludes,101Standard);102
103// Some options are "on by default", but e.g. at the driver level.104if (Opts.CPlusPlus)105Opts.CXXOperatorNames = true;106if (Opts.CPlusPlus20)107Opts.Coroutines = true;108
109// Some options are off by default, but define keywords we want to tolerate.110if (Opts.CPlusPlus)111Opts.MicrosoftExt = true; // kw__try, kw__finally112Opts.DeclSpecKeyword = true; // __declspec113Opts.WChar = true;114
115return Opts;116}
117
118TokenStream stripComments(const TokenStream &Input) {119TokenStream Out(Input.getPayload());120for (const Token &T : Input.tokens()) {121if (T.Kind == tok::comment)122continue;123Out.push(T);124}125Out.finalize();126return Out;127}
128
129} // namespace pseudo130} // namespace clang131