1 //===-- CPlusPlusNameParser.h -----------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H
10 #define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H
12 #include "clang/Lex/Lexer.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/ADT/StringRef.h"
16 #include "lldb/Utility/ConstString.h"
17 #include "lldb/lldb-private.h"
20 namespace lldb_private
{
22 // Helps to validate and obtain various parts of C++ definitions.
23 class CPlusPlusNameParser
{
25 CPlusPlusNameParser(llvm::StringRef text
) : m_text(text
) { ExtractTokens(); }
28 llvm::StringRef basename
;
29 llvm::StringRef context
;
32 struct ParsedFunction
{
34 llvm::StringRef arguments
;
35 llvm::StringRef qualifiers
;
36 llvm::StringRef return_type
;
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.
43 // main(int, chat const*)
45 // std::vector<int>::push_back(int)
46 // int& map<int, pair<short, int>>::operator[](short) const
47 // int (*get_function(const chat *))()
48 std::optional
<ParsedFunction
> ParseAsFunctionDefinition();
50 // Treats given text as a potentially nested name of C++ entity (function,
51 // class, field) and parses it.
55 // std::vector<int>::push_back
56 // map<int, pair<short, int>>::operator[]
57 // func<C>(int, C&)::nested_class::method
58 std::optional
<ParsedName
> ParseAsFullName();
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;
68 // Range of tokens saved in m_next_token_index.
70 size_t begin_index
= 0;
74 Range(size_t begin
, size_t end
) : begin_index(begin
), end_index(end
) {
78 size_t size() const { return end_index
- begin_index
; }
80 bool empty() const { return size() == 0; }
83 struct ParsedNameRanges
{
88 // Bookmark automatically restores parsing position (m_next_token_index)
89 // when destructed unless it's manually removed with Remove().
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
) {
100 Bookmark
&operator=(Bookmark
&&) = delete;
101 Bookmark
&operator=(const Bookmark
&) = delete;
103 void Remove() { m_restore
= false; }
104 size_t GetSavedPosition() { return m_position_value
; }
107 m_position
= m_position_value
;
113 size_t m_position_value
;
114 bool m_restore
= true;
117 bool HasMoreTokens();
120 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
);
128 std::optional
<ParsedFunction
> ParseFunctionImpl(bool expect_return_type
);
130 // Parses functions returning function pointers 'string (*f(int x))(float y)'
131 std::optional
<ParsedFunction
> ParseFuncPtr(bool expect_return_type
);
133 // Consumes function arguments enclosed within '(' ... ')'
134 bool ConsumeArguments();
136 // Consumes template arguments enclosed within '<' ... '>'
137 bool ConsumeTemplateArgs();
139 // Consumes '(anonymous namespace)'
140 bool ConsumeAnonymousNamespace();
142 // Consumes '{lambda ...}'
143 bool ConsumeLambda();
145 // Consumes operator declaration like 'operator *' or 'operator delete []'
146 bool ConsumeOperator();
148 // Skips 'const' and 'volatile'
149 void SkipTypeQualifiers();
151 // Skips 'const', 'volatile', '&', '&&' in the end of the function.
152 void SkipFunctionQualifiers();
154 // Consumes built-in types like 'int' or 'unsigned long long int'
155 bool ConsumeBuiltinType();
157 // Consumes types defined via decltype keyword.
158 bool ConsumeDecltype();
160 // Skips 'const' and 'volatile'
161 void SkipPtrsAndRefs();
163 // Consumes things like 'const * const &'
164 bool ConsumePtrsAndRefs();
166 // Consumes full type name like 'Namespace::Class<int>::Method()::InnerClass'
167 bool ConsumeTypename();
169 /// Consumes ABI tags enclosed within '[abi:' ... ']'
171 /// Since there is no restriction on what the ABI tag
172 /// string may contain, this API supports parsing a small
173 /// set of special characters.
175 /// The following regex describes the set of supported characters:
177 bool ConsumeAbiTag();
179 std::optional
<ParsedNameRanges
> ParseFullNameImpl();
180 llvm::StringRef
GetTextForRange(const Range
&range
);
182 // Populate m_tokens by calling clang lexer on m_text.
183 void ExtractTokens();
186 } // namespace lldb_private
188 #endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H