blob: f936fb787c9437125dcc2f9f74c32e7458bd3ee5 [file] [log] [blame]
Eugene Zemtsova633ee62017-04-06 22:36:02 +00001//===-- 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_