1061da546Spatrick //===-- CPlusPlusNameParser.h -----------------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H 10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H 11061da546Spatrick 12061da546Spatrick #include "clang/Lex/Lexer.h" 13061da546Spatrick #include "llvm/ADT/SmallVector.h" 14061da546Spatrick #include "llvm/ADT/StringRef.h" 15061da546Spatrick 16061da546Spatrick #include "lldb/Utility/ConstString.h" 17061da546Spatrick #include "lldb/lldb-private.h" 18*f6aab3d8Srobert #include <optional> 19061da546Spatrick 20061da546Spatrick namespace lldb_private { 21061da546Spatrick 22061da546Spatrick // Helps to validate and obtain various parts of C++ definitions. 23061da546Spatrick class CPlusPlusNameParser { 24061da546Spatrick public: CPlusPlusNameParser(llvm::StringRef text)25061da546Spatrick CPlusPlusNameParser(llvm::StringRef text) : m_text(text) { ExtractTokens(); } 26061da546Spatrick 27061da546Spatrick struct ParsedName { 28061da546Spatrick llvm::StringRef basename; 29061da546Spatrick llvm::StringRef context; 30061da546Spatrick }; 31061da546Spatrick 32061da546Spatrick struct ParsedFunction { 33061da546Spatrick ParsedName name; 34061da546Spatrick llvm::StringRef arguments; 35061da546Spatrick llvm::StringRef qualifiers; 36*f6aab3d8Srobert llvm::StringRef return_type; 37061da546Spatrick }; 38061da546Spatrick 39061da546Spatrick // Treats given text as a function definition and parses it. 40061da546Spatrick // Function definition might or might not have a return type and this should 41061da546Spatrick // change parsing result. 42061da546Spatrick // Examples: 43061da546Spatrick // main(int, chat const*) 44061da546Spatrick // T fun(int, bool) 45061da546Spatrick // std::vector<int>::push_back(int) 46061da546Spatrick // int& map<int, pair<short, int>>::operator[](short) const 47061da546Spatrick // int (*get_function(const chat *))() 48*f6aab3d8Srobert std::optional<ParsedFunction> ParseAsFunctionDefinition(); 49061da546Spatrick 50061da546Spatrick // Treats given text as a potentially nested name of C++ entity (function, 51061da546Spatrick // class, field) and parses it. 52061da546Spatrick // Examples: 53061da546Spatrick // main 54061da546Spatrick // fun 55061da546Spatrick // std::vector<int>::push_back 56061da546Spatrick // map<int, pair<short, int>>::operator[] 57061da546Spatrick // func<C>(int, C&)::nested_class::method 58*f6aab3d8Srobert std::optional<ParsedName> ParseAsFullName(); 59061da546Spatrick 60061da546Spatrick private: 61061da546Spatrick // A C++ definition to parse. 62061da546Spatrick llvm::StringRef m_text; 63061da546Spatrick // Tokens extracted from m_text. 64061da546Spatrick llvm::SmallVector<clang::Token, 30> m_tokens; 65061da546Spatrick // Index of the next token to look at from m_tokens. 66061da546Spatrick size_t m_next_token_index = 0; 67061da546Spatrick 68061da546Spatrick // Range of tokens saved in m_next_token_index. 69061da546Spatrick struct Range { 70061da546Spatrick size_t begin_index = 0; 71061da546Spatrick size_t end_index = 0; 72061da546Spatrick 73be691f3bSpatrick Range() = default; RangeRange74061da546Spatrick Range(size_t begin, size_t end) : begin_index(begin), end_index(end) { 75061da546Spatrick assert(end >= begin); 76061da546Spatrick } 77061da546Spatrick sizeRange78061da546Spatrick size_t size() const { return end_index - begin_index; } 79061da546Spatrick emptyRange80061da546Spatrick bool empty() const { return size() == 0; } 81061da546Spatrick }; 82061da546Spatrick 83061da546Spatrick struct ParsedNameRanges { 84061da546Spatrick Range basename_range; 85061da546Spatrick Range context_range; 86061da546Spatrick }; 87061da546Spatrick 88061da546Spatrick // Bookmark automatically restores parsing position (m_next_token_index) 89061da546Spatrick // when destructed unless it's manually removed with Remove(). 90061da546Spatrick class Bookmark { 91061da546Spatrick public: Bookmark(size_t & position)92061da546Spatrick Bookmark(size_t &position) 93061da546Spatrick : m_position(position), m_position_value(position) {} 94061da546Spatrick Bookmark(const Bookmark &) = delete; Bookmark(Bookmark && b)95061da546Spatrick Bookmark(Bookmark &&b) 96061da546Spatrick : m_position(b.m_position), m_position_value(b.m_position_value), 97061da546Spatrick m_restore(b.m_restore) { 98061da546Spatrick b.Remove(); 99061da546Spatrick } 100061da546Spatrick Bookmark &operator=(Bookmark &&) = delete; 101061da546Spatrick Bookmark &operator=(const Bookmark &) = delete; 102061da546Spatrick Remove()103061da546Spatrick void Remove() { m_restore = false; } GetSavedPosition()104061da546Spatrick size_t GetSavedPosition() { return m_position_value; } ~Bookmark()105061da546Spatrick ~Bookmark() { 106061da546Spatrick if (m_restore) { 107061da546Spatrick m_position = m_position_value; 108061da546Spatrick } 109061da546Spatrick } 110061da546Spatrick 111061da546Spatrick private: 112061da546Spatrick size_t &m_position; 113061da546Spatrick size_t m_position_value; 114061da546Spatrick bool m_restore = true; 115061da546Spatrick }; 116061da546Spatrick 117061da546Spatrick bool HasMoreTokens(); 118061da546Spatrick void Advance(); 119061da546Spatrick void TakeBack(); 120061da546Spatrick bool ConsumeToken(clang::tok::TokenKind kind); 121*f6aab3d8Srobert 122061da546Spatrick template <typename... Ts> bool ConsumeToken(Ts... kinds); 123061da546Spatrick Bookmark SetBookmark(); 124061da546Spatrick size_t GetCurrentPosition(); 125061da546Spatrick clang::Token &Peek(); 126061da546Spatrick bool ConsumeBrackets(clang::tok::TokenKind left, clang::tok::TokenKind right); 127061da546Spatrick 128*f6aab3d8Srobert std::optional<ParsedFunction> ParseFunctionImpl(bool expect_return_type); 129061da546Spatrick 130061da546Spatrick // Parses functions returning function pointers 'string (*f(int x))(float y)' 131*f6aab3d8Srobert std::optional<ParsedFunction> ParseFuncPtr(bool expect_return_type); 132061da546Spatrick 133061da546Spatrick // Consumes function arguments enclosed within '(' ... ')' 134061da546Spatrick bool ConsumeArguments(); 135061da546Spatrick 136061da546Spatrick // Consumes template arguments enclosed within '<' ... '>' 137061da546Spatrick bool ConsumeTemplateArgs(); 138061da546Spatrick 139061da546Spatrick // Consumes '(anonymous namespace)' 140061da546Spatrick bool ConsumeAnonymousNamespace(); 141061da546Spatrick 142061da546Spatrick // Consumes '{lambda ...}' 143061da546Spatrick bool ConsumeLambda(); 144061da546Spatrick 145061da546Spatrick // Consumes operator declaration like 'operator *' or 'operator delete []' 146061da546Spatrick bool ConsumeOperator(); 147061da546Spatrick 148061da546Spatrick // Skips 'const' and 'volatile' 149061da546Spatrick void SkipTypeQualifiers(); 150061da546Spatrick 151061da546Spatrick // Skips 'const', 'volatile', '&', '&&' in the end of the function. 152061da546Spatrick void SkipFunctionQualifiers(); 153061da546Spatrick 154061da546Spatrick // Consumes built-in types like 'int' or 'unsigned long long int' 155061da546Spatrick bool ConsumeBuiltinType(); 156061da546Spatrick 157061da546Spatrick // Consumes types defined via decltype keyword. 158061da546Spatrick bool ConsumeDecltype(); 159061da546Spatrick 160061da546Spatrick // Skips 'const' and 'volatile' 161061da546Spatrick void SkipPtrsAndRefs(); 162061da546Spatrick 163061da546Spatrick // Consumes things like 'const * const &' 164061da546Spatrick bool ConsumePtrsAndRefs(); 165061da546Spatrick 166061da546Spatrick // Consumes full type name like 'Namespace::Class<int>::Method()::InnerClass' 167061da546Spatrick bool ConsumeTypename(); 168061da546Spatrick 169*f6aab3d8Srobert /// Consumes ABI tags enclosed within '[abi:' ... ']' 170*f6aab3d8Srobert /// 171*f6aab3d8Srobert /// Since there is no restriction on what the ABI tag 172*f6aab3d8Srobert /// string may contain, this API supports parsing a small 173*f6aab3d8Srobert /// set of special characters. 174*f6aab3d8Srobert /// 175*f6aab3d8Srobert /// The following regex describes the set of supported characters: 176*f6aab3d8Srobert /// [A-Za-z,.\s\d]+ 177*f6aab3d8Srobert bool ConsumeAbiTag(); 178*f6aab3d8Srobert 179*f6aab3d8Srobert std::optional<ParsedNameRanges> ParseFullNameImpl(); 180061da546Spatrick llvm::StringRef GetTextForRange(const Range &range); 181061da546Spatrick 182061da546Spatrick // Populate m_tokens by calling clang lexer on m_text. 183061da546Spatrick void ExtractTokens(); 184061da546Spatrick }; 185061da546Spatrick 186061da546Spatrick } // namespace lldb_private 187061da546Spatrick 188dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H 189