CPlusPlusNameParser.h revision 353358
1//===-- CPlusPlusNameParser.h -----------------------------------*- C++ -*-===// 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#ifndef liblldb_CPlusPlusNameParser_h_ 10#define liblldb_CPlusPlusNameParser_h_ 11 12 13#include "clang/Lex/Lexer.h" 14#include "llvm/ADT/Optional.h" 15#include "llvm/ADT/SmallVector.h" 16#include "llvm/ADT/StringRef.h" 17 18#include "lldb/Utility/ConstString.h" 19#include "lldb/lldb-private.h" 20 21namespace lldb_private { 22 23// Helps to validate and obtain various parts of C++ definitions. 24class CPlusPlusNameParser { 25public: 26 CPlusPlusNameParser(llvm::StringRef text) : m_text(text) { ExtractTokens(); } 27 28 struct ParsedName { 29 llvm::StringRef basename; 30 llvm::StringRef context; 31 }; 32 33 struct ParsedFunction { 34 ParsedName name; 35 llvm::StringRef arguments; 36 llvm::StringRef qualifiers; 37 }; 38 39 // Treats given text as a function definition and parses it. 40 // Function definition might or might not have a return type and this should 41 // change parsing result. 42 // Examples: 43 // main(int, chat const*) 44 // T fun(int, bool) 45 // std::vector<int>::push_back(int) 46 // int& map<int, pair<short, int>>::operator[](short) const 47 // int (*get_function(const chat *))() 48 llvm::Optional<ParsedFunction> ParseAsFunctionDefinition(); 49 50 // Treats given text as a potentially nested name of C++ entity (function, 51 // class, field) and parses it. 52 // Examples: 53 // main 54 // fun 55 // std::vector<int>::push_back 56 // map<int, pair<short, int>>::operator[] 57 // func<C>(int, C&)::nested_class::method 58 llvm::Optional<ParsedName> ParseAsFullName(); 59 60private: 61 // A C++ definition to parse. 62 llvm::StringRef m_text; 63 // Tokens extracted from m_text. 64 llvm::SmallVector<clang::Token, 30> m_tokens; 65 // Index of the next token to look at from m_tokens. 66 size_t m_next_token_index = 0; 67 68 // Range of tokens saved in m_next_token_index. 69 struct Range { 70 size_t begin_index = 0; 71 size_t end_index = 0; 72 73 Range() {} 74 Range(size_t begin, size_t end) : begin_index(begin), end_index(end) { 75 assert(end >= begin); 76 } 77 78 size_t size() const { return end_index - begin_index; } 79 80 bool empty() const { return size() == 0; } 81 }; 82 83 struct ParsedNameRanges { 84 Range basename_range; 85 Range context_range; 86 }; 87 88 // Bookmark automatically restores parsing position (m_next_token_index) 89 // when destructed unless it's manually removed with Remove(). 90 class Bookmark { 91 public: 92 Bookmark(size_t &position) 93 : m_position(position), m_position_value(position) {} 94 Bookmark(const Bookmark &) = delete; 95 Bookmark(Bookmark &&b) 96 : m_position(b.m_position), m_position_value(b.m_position_value), 97 m_restore(b.m_restore) { 98 b.Remove(); 99 } 100 Bookmark &operator=(Bookmark &&) = delete; 101 Bookmark &operator=(const Bookmark &) = delete; 102 103 void Remove() { m_restore = false; } 104 size_t GetSavedPosition() { return m_position_value; } 105 ~Bookmark() { 106 if (m_restore) { 107 m_position = m_position_value; 108 } 109 } 110 111 private: 112 size_t &m_position; 113 size_t m_position_value; 114 bool m_restore = true; 115 }; 116 117 bool HasMoreTokens(); 118 void Advance(); 119 void TakeBack(); 120 bool ConsumeToken(clang::tok::TokenKind kind); 121 template <typename... Ts> bool ConsumeToken(Ts... kinds); 122 Bookmark SetBookmark(); 123 size_t GetCurrentPosition(); 124 clang::Token &Peek(); 125 bool ConsumeBrackets(clang::tok::TokenKind left, clang::tok::TokenKind right); 126 127 llvm::Optional<ParsedFunction> ParseFunctionImpl(bool expect_return_type); 128 129 // Parses functions returning function pointers 'string (*f(int x))(float y)' 130 llvm::Optional<ParsedFunction> ParseFuncPtr(bool expect_return_type); 131 132 // Consumes function arguments enclosed within '(' ... ')' 133 bool ConsumeArguments(); 134 135 // Consumes template arguments enclosed within '<' ... '>' 136 bool ConsumeTemplateArgs(); 137 138 // Consumes '(anonymous namespace)' 139 bool ConsumeAnonymousNamespace(); 140 141 // Consumes '{lambda ...}' 142 bool ConsumeLambda(); 143 144 // Consumes operator declaration like 'operator *' or 'operator delete []' 145 bool ConsumeOperator(); 146 147 // Skips 'const' and 'volatile' 148 void SkipTypeQualifiers(); 149 150 // Skips 'const', 'volatile', '&', '&&' in the end of the function. 151 void SkipFunctionQualifiers(); 152 153 // Consumes built-in types like 'int' or 'unsigned long long int' 154 bool ConsumeBuiltinType(); 155 156 // Consumes types defined via decltype keyword. 157 bool ConsumeDecltype(); 158 159 // Skips 'const' and 'volatile' 160 void SkipPtrsAndRefs(); 161 162 // Consumes things like 'const * const &' 163 bool ConsumePtrsAndRefs(); 164 165 // Consumes full type name like 'Namespace::Class<int>::Method()::InnerClass' 166 bool ConsumeTypename(); 167 168 llvm::Optional<ParsedNameRanges> ParseFullNameImpl(); 169 llvm::StringRef GetTextForRange(const Range &range); 170 171 // Populate m_tokens by calling clang lexer on m_text. 172 void ExtractTokens(); 173}; 174 175} // namespace lldb_private 176 177#endif // liblldb_CPlusPlusNameParser_h_ 178