diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang14/lib/Format/MacroExpander.cpp | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang14/lib/Format/MacroExpander.cpp')
-rw-r--r-- | contrib/libs/clang14/lib/Format/MacroExpander.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/contrib/libs/clang14/lib/Format/MacroExpander.cpp b/contrib/libs/clang14/lib/Format/MacroExpander.cpp new file mode 100644 index 0000000000..de96cb24ba --- /dev/null +++ b/contrib/libs/clang14/lib/Format/MacroExpander.cpp @@ -0,0 +1,223 @@ +//===--- MacroExpander.cpp - Format C++ code --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the implementation of MacroExpander, which handles macro +/// configuration and expansion while formatting. +/// +//===----------------------------------------------------------------------===// + +#include "Macros.h" + +#include "Encoding.h" +#include "FormatToken.h" +#include "FormatTokenLexer.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Format/Format.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/ModuleLoader.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/ErrorHandling.h" + +namespace clang { +namespace format { + +struct MacroExpander::Definition { + StringRef Name; + SmallVector<FormatToken *, 8> Params; + SmallVector<FormatToken *, 8> Body; + + // Map from each argument's name to its position in the argument list. + // With "M(x, y) x + y": + // x -> 0 + // y -> 1 + llvm::StringMap<size_t> ArgMap; + + bool ObjectLike = true; +}; + +class MacroExpander::DefinitionParser { +public: + DefinitionParser(ArrayRef<FormatToken *> Tokens) : Tokens(Tokens) { + assert(!Tokens.empty()); + Current = Tokens[0]; + } + + // Parse the token stream and return the corresponding Definition object. + // Returns an empty definition object with a null-Name on error. + MacroExpander::Definition parse() { + if (!Current->is(tok::identifier)) + return {}; + Def.Name = Current->TokenText; + nextToken(); + if (Current->is(tok::l_paren)) { + Def.ObjectLike = false; + if (!parseParams()) + return {}; + } + if (!parseExpansion()) + return {}; + + return Def; + } + +private: + bool parseParams() { + assert(Current->is(tok::l_paren)); + nextToken(); + while (Current->is(tok::identifier)) { + Def.Params.push_back(Current); + Def.ArgMap[Def.Params.back()->TokenText] = Def.Params.size() - 1; + nextToken(); + if (Current->isNot(tok::comma)) + break; + nextToken(); + } + if (Current->isNot(tok::r_paren)) + return false; + nextToken(); + return true; + } + + bool parseExpansion() { + if (!Current->isOneOf(tok::equal, tok::eof)) + return false; + if (Current->is(tok::equal)) + nextToken(); + parseTail(); + return true; + } + + void parseTail() { + while (Current->isNot(tok::eof)) { + Def.Body.push_back(Current); + nextToken(); + } + Def.Body.push_back(Current); + } + + void nextToken() { + if (Pos + 1 < Tokens.size()) + ++Pos; + Current = Tokens[Pos]; + Current->Finalized = true; + } + + size_t Pos = 0; + FormatToken *Current = nullptr; + Definition Def; + ArrayRef<FormatToken *> Tokens; +}; + +MacroExpander::MacroExpander( + const std::vector<std::string> &Macros, clang::SourceManager &SourceMgr, + const FormatStyle &Style, + llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator, + IdentifierTable &IdentTable) + : SourceMgr(SourceMgr), Style(Style), Allocator(Allocator), + IdentTable(IdentTable) { + for (const std::string &Macro : Macros) { + parseDefinition(Macro); + } +} + +MacroExpander::~MacroExpander() = default; + +void MacroExpander::parseDefinition(const std::string &Macro) { + Buffers.push_back( + llvm::MemoryBuffer::getMemBufferCopy(Macro, "<scratch space>")); + clang::FileID FID = SourceMgr.createFileID(Buffers.back()->getMemBufferRef()); + FormatTokenLexer Lex(SourceMgr, FID, 0, Style, encoding::Encoding_UTF8, + Allocator, IdentTable); + const auto Tokens = Lex.lex(); + if (!Tokens.empty()) { + DefinitionParser Parser(Tokens); + auto Definition = Parser.parse(); + Definitions[Definition.Name] = std::move(Definition); + } +} + +bool MacroExpander::defined(llvm::StringRef Name) const { + return Definitions.find(Name) != Definitions.end(); +} + +bool MacroExpander::objectLike(llvm::StringRef Name) const { + return Definitions.find(Name)->second.ObjectLike; +} + +llvm::SmallVector<FormatToken *, 8> MacroExpander::expand(FormatToken *ID, + ArgsList Args) const { + assert(defined(ID->TokenText)); + SmallVector<FormatToken *, 8> Result; + const Definition &Def = Definitions.find(ID->TokenText)->second; + + // Expand each argument at most once. + llvm::StringSet<> ExpandedArgs; + + // Adds the given token to Result. + auto pushToken = [&](FormatToken *Tok) { + Tok->MacroCtx->ExpandedFrom.push_back(ID); + Result.push_back(Tok); + }; + + // If Tok references a parameter, adds the corresponding argument to Result. + // Returns false if Tok does not reference a parameter. + auto expandArgument = [&](FormatToken *Tok) -> bool { + // If the current token references a parameter, expand the corresponding + // argument. + if (!Tok->is(tok::identifier) || ExpandedArgs.contains(Tok->TokenText)) + return false; + ExpandedArgs.insert(Tok->TokenText); + auto I = Def.ArgMap.find(Tok->TokenText); + if (I == Def.ArgMap.end()) + return false; + // If there are fewer arguments than referenced parameters, treat the + // parameter as empty. + // FIXME: Potentially fully abort the expansion instead. + if (I->getValue() >= Args.size()) + return true; + for (FormatToken *Arg : Args[I->getValue()]) { + // A token can be part of a macro argument at multiple levels. + // For example, with "ID(x) x": + // in ID(ID(x)), 'x' is expanded first as argument to the inner + // ID, then again as argument to the outer ID. We keep the macro + // role the token had from the inner expansion. + if (!Arg->MacroCtx) + Arg->MacroCtx = MacroExpansion(MR_ExpandedArg); + pushToken(Arg); + } + return true; + }; + + // Expand the definition into Result. + for (FormatToken *Tok : Def.Body) { + if (expandArgument(Tok)) + continue; + // Create a copy of the tokens from the macro body, i.e. were not provided + // by user code. + FormatToken *New = new (Allocator.Allocate()) FormatToken; + New->copyFrom(*Tok); + assert(!New->MacroCtx); + // Tokens that are not part of the user code are not formatted. + New->MacroCtx = MacroExpansion(MR_Hidden); + pushToken(New); + } + assert(Result.size() >= 1 && Result.back()->is(tok::eof)); + if (Result.size() > 1) { + ++Result[0]->MacroCtx->StartOfExpansion; + ++Result[Result.size() - 2]->MacroCtx->EndOfExpansion; + } + return Result; +} + +} // namespace format +} // namespace clang |