//===-- CPlusPlusNameParser.h -----------------------------------*- 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 // //===----------------------------------------------------------------------===// #ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H #define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H #include "clang/Lex/Lexer.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "lldb/Utility/ConstString.h" #include "lldb/lldb-private.h" #include namespace lldb_private { // Helps to validate and obtain various parts of C++ definitions. class CPlusPlusNameParser { public: CPlusPlusNameParser(llvm::StringRef text) : m_text(text) { ExtractTokens(); } struct ParsedName { llvm::StringRef basename; llvm::StringRef context; }; struct ParsedFunction { ParsedName name; llvm::StringRef arguments; llvm::StringRef qualifiers; llvm::StringRef return_type; }; // Treats given text as a function definition and parses it. // Function definition might or might not have a return type and this should // change parsing result. // Examples: // main(int, chat const*) // T fun(int, bool) // std::vector::push_back(int) // int& map>::operator[](short) const // int (*get_function(const chat *))() std::optional ParseAsFunctionDefinition(); // Treats given text as a potentially nested name of C++ entity (function, // class, field) and parses it. // Examples: // main // fun // std::vector::push_back // map>::operator[] // func(int, C&)::nested_class::method std::optional ParseAsFullName(); private: // A C++ definition to parse. llvm::StringRef m_text; // Tokens extracted from m_text. llvm::SmallVector m_tokens; // Index of the next token to look at from m_tokens. size_t m_next_token_index = 0; // Range of tokens saved in m_next_token_index. struct Range { size_t begin_index = 0; size_t end_index = 0; Range() = default; Range(size_t begin, size_t end) : begin_index(begin), end_index(end) { assert(end >= begin); } size_t size() const { return end_index - begin_index; } bool empty() const { return size() == 0; } }; struct ParsedNameRanges { Range basename_range; Range context_range; }; // Bookmark automatically restores parsing position (m_next_token_index) // when destructed unless it's manually removed with Remove(). class Bookmark { public: Bookmark(size_t &position) : m_position(position), m_position_value(position) {} Bookmark(const Bookmark &) = delete; Bookmark(Bookmark &&b) : m_position(b.m_position), m_position_value(b.m_position_value), m_restore(b.m_restore) { b.Remove(); } Bookmark &operator=(Bookmark &&) = delete; Bookmark &operator=(const Bookmark &) = delete; void Remove() { m_restore = false; } size_t GetSavedPosition() { return m_position_value; } ~Bookmark() { if (m_restore) { m_position = m_position_value; } } private: size_t &m_position; size_t m_position_value; bool m_restore = true; }; bool HasMoreTokens(); void Advance(); void TakeBack(); bool ConsumeToken(clang::tok::TokenKind kind); template bool ConsumeToken(Ts... kinds); Bookmark SetBookmark(); size_t GetCurrentPosition(); clang::Token &Peek(); bool ConsumeBrackets(clang::tok::TokenKind left, clang::tok::TokenKind right); std::optional ParseFunctionImpl(bool expect_return_type); // Parses functions returning function pointers 'string (*f(int x))(float y)' std::optional ParseFuncPtr(bool expect_return_type); // Consumes function arguments enclosed within '(' ... ')' bool ConsumeArguments(); // Consumes template arguments enclosed within '<' ... '>' bool ConsumeTemplateArgs(); // Consumes '(anonymous namespace)' bool ConsumeAnonymousNamespace(); // Consumes '{lambda ...}' bool ConsumeLambda(); // Consumes operator declaration like 'operator *' or 'operator delete []' bool ConsumeOperator(); // Skips 'const' and 'volatile' void SkipTypeQualifiers(); // Skips 'const', 'volatile', '&', '&&' in the end of the function. void SkipFunctionQualifiers(); // Consumes built-in types like 'int' or 'unsigned long long int' bool ConsumeBuiltinType(); // Consumes types defined via decltype keyword. bool ConsumeDecltype(); // Skips 'const' and 'volatile' void SkipPtrsAndRefs(); // Consumes things like 'const * const &' bool ConsumePtrsAndRefs(); // Consumes full type name like 'Namespace::Class::Method()::InnerClass' bool ConsumeTypename(); /// Consumes ABI tags enclosed within '[abi:' ... ']' /// /// Since there is no restriction on what the ABI tag /// string may contain, this API supports parsing a small /// set of special characters. /// /// The following regex describes the set of supported characters: /// [A-Za-z,.\s\d]+ bool ConsumeAbiTag(); std::optional ParseFullNameImpl(); llvm::StringRef GetTextForRange(const Range &range); // Populate m_tokens by calling clang lexer on m_text. void ExtractTokens(); }; } // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H