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