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