xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1061da546Spatrick //===-- CPlusPlusNameParser.h -----------------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H
10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H
11061da546Spatrick 
12061da546Spatrick #include "clang/Lex/Lexer.h"
13061da546Spatrick #include "llvm/ADT/SmallVector.h"
14061da546Spatrick #include "llvm/ADT/StringRef.h"
15061da546Spatrick 
16061da546Spatrick #include "lldb/Utility/ConstString.h"
17061da546Spatrick #include "lldb/lldb-private.h"
18*f6aab3d8Srobert #include <optional>
19061da546Spatrick 
20061da546Spatrick namespace lldb_private {
21061da546Spatrick 
22061da546Spatrick // Helps to validate and obtain various parts of C++ definitions.
23061da546Spatrick class CPlusPlusNameParser {
24061da546Spatrick public:
CPlusPlusNameParser(llvm::StringRef text)25061da546Spatrick   CPlusPlusNameParser(llvm::StringRef text) : m_text(text) { ExtractTokens(); }
26061da546Spatrick 
27061da546Spatrick   struct ParsedName {
28061da546Spatrick     llvm::StringRef basename;
29061da546Spatrick     llvm::StringRef context;
30061da546Spatrick   };
31061da546Spatrick 
32061da546Spatrick   struct ParsedFunction {
33061da546Spatrick     ParsedName name;
34061da546Spatrick     llvm::StringRef arguments;
35061da546Spatrick     llvm::StringRef qualifiers;
36*f6aab3d8Srobert     llvm::StringRef return_type;
37061da546Spatrick   };
38061da546Spatrick 
39061da546Spatrick   // Treats given text as a function definition and parses it.
40061da546Spatrick   // Function definition might or might not have a return type and this should
41061da546Spatrick   // change parsing result.
42061da546Spatrick   // Examples:
43061da546Spatrick   //    main(int, chat const*)
44061da546Spatrick   //    T fun(int, bool)
45061da546Spatrick   //    std::vector<int>::push_back(int)
46061da546Spatrick   //    int& map<int, pair<short, int>>::operator[](short) const
47061da546Spatrick   //    int (*get_function(const chat *))()
48*f6aab3d8Srobert   std::optional<ParsedFunction> ParseAsFunctionDefinition();
49061da546Spatrick 
50061da546Spatrick   // Treats given text as a potentially nested name of C++ entity (function,
51061da546Spatrick   // class, field) and parses it.
52061da546Spatrick   // Examples:
53061da546Spatrick   //    main
54061da546Spatrick   //    fun
55061da546Spatrick   //    std::vector<int>::push_back
56061da546Spatrick   //    map<int, pair<short, int>>::operator[]
57061da546Spatrick   //    func<C>(int, C&)::nested_class::method
58*f6aab3d8Srobert   std::optional<ParsedName> ParseAsFullName();
59061da546Spatrick 
60061da546Spatrick private:
61061da546Spatrick   // A C++ definition to parse.
62061da546Spatrick   llvm::StringRef m_text;
63061da546Spatrick   // Tokens extracted from m_text.
64061da546Spatrick   llvm::SmallVector<clang::Token, 30> m_tokens;
65061da546Spatrick   // Index of the next token to look at from m_tokens.
66061da546Spatrick   size_t m_next_token_index = 0;
67061da546Spatrick 
68061da546Spatrick   // Range of tokens saved in m_next_token_index.
69061da546Spatrick   struct Range {
70061da546Spatrick     size_t begin_index = 0;
71061da546Spatrick     size_t end_index = 0;
72061da546Spatrick 
73be691f3bSpatrick     Range() = default;
RangeRange74061da546Spatrick     Range(size_t begin, size_t end) : begin_index(begin), end_index(end) {
75061da546Spatrick       assert(end >= begin);
76061da546Spatrick     }
77061da546Spatrick 
sizeRange78061da546Spatrick     size_t size() const { return end_index - begin_index; }
79061da546Spatrick 
emptyRange80061da546Spatrick     bool empty() const { return size() == 0; }
81061da546Spatrick   };
82061da546Spatrick 
83061da546Spatrick   struct ParsedNameRanges {
84061da546Spatrick     Range basename_range;
85061da546Spatrick     Range context_range;
86061da546Spatrick   };
87061da546Spatrick 
88061da546Spatrick   // Bookmark automatically restores parsing position (m_next_token_index)
89061da546Spatrick   // when destructed unless it's manually removed with Remove().
90061da546Spatrick   class Bookmark {
91061da546Spatrick   public:
Bookmark(size_t & position)92061da546Spatrick     Bookmark(size_t &position)
93061da546Spatrick         : m_position(position), m_position_value(position) {}
94061da546Spatrick     Bookmark(const Bookmark &) = delete;
Bookmark(Bookmark && b)95061da546Spatrick     Bookmark(Bookmark &&b)
96061da546Spatrick         : m_position(b.m_position), m_position_value(b.m_position_value),
97061da546Spatrick           m_restore(b.m_restore) {
98061da546Spatrick       b.Remove();
99061da546Spatrick     }
100061da546Spatrick     Bookmark &operator=(Bookmark &&) = delete;
101061da546Spatrick     Bookmark &operator=(const Bookmark &) = delete;
102061da546Spatrick 
Remove()103061da546Spatrick     void Remove() { m_restore = false; }
GetSavedPosition()104061da546Spatrick     size_t GetSavedPosition() { return m_position_value; }
~Bookmark()105061da546Spatrick     ~Bookmark() {
106061da546Spatrick       if (m_restore) {
107061da546Spatrick         m_position = m_position_value;
108061da546Spatrick       }
109061da546Spatrick     }
110061da546Spatrick 
111061da546Spatrick   private:
112061da546Spatrick     size_t &m_position;
113061da546Spatrick     size_t m_position_value;
114061da546Spatrick     bool m_restore = true;
115061da546Spatrick   };
116061da546Spatrick 
117061da546Spatrick   bool HasMoreTokens();
118061da546Spatrick   void Advance();
119061da546Spatrick   void TakeBack();
120061da546Spatrick   bool ConsumeToken(clang::tok::TokenKind kind);
121*f6aab3d8Srobert 
122061da546Spatrick   template <typename... Ts> bool ConsumeToken(Ts... kinds);
123061da546Spatrick   Bookmark SetBookmark();
124061da546Spatrick   size_t GetCurrentPosition();
125061da546Spatrick   clang::Token &Peek();
126061da546Spatrick   bool ConsumeBrackets(clang::tok::TokenKind left, clang::tok::TokenKind right);
127061da546Spatrick 
128*f6aab3d8Srobert   std::optional<ParsedFunction> ParseFunctionImpl(bool expect_return_type);
129061da546Spatrick 
130061da546Spatrick   // Parses functions returning function pointers 'string (*f(int x))(float y)'
131*f6aab3d8Srobert   std::optional<ParsedFunction> ParseFuncPtr(bool expect_return_type);
132061da546Spatrick 
133061da546Spatrick   // Consumes function arguments enclosed within '(' ... ')'
134061da546Spatrick   bool ConsumeArguments();
135061da546Spatrick 
136061da546Spatrick   // Consumes template arguments enclosed within '<' ... '>'
137061da546Spatrick   bool ConsumeTemplateArgs();
138061da546Spatrick 
139061da546Spatrick   // Consumes '(anonymous namespace)'
140061da546Spatrick   bool ConsumeAnonymousNamespace();
141061da546Spatrick 
142061da546Spatrick   // Consumes '{lambda ...}'
143061da546Spatrick   bool ConsumeLambda();
144061da546Spatrick 
145061da546Spatrick   // Consumes operator declaration like 'operator *' or 'operator delete []'
146061da546Spatrick   bool ConsumeOperator();
147061da546Spatrick 
148061da546Spatrick   // Skips 'const' and 'volatile'
149061da546Spatrick   void SkipTypeQualifiers();
150061da546Spatrick 
151061da546Spatrick   // Skips 'const', 'volatile', '&', '&&' in the end of the function.
152061da546Spatrick   void SkipFunctionQualifiers();
153061da546Spatrick 
154061da546Spatrick   // Consumes built-in types like 'int' or 'unsigned long long int'
155061da546Spatrick   bool ConsumeBuiltinType();
156061da546Spatrick 
157061da546Spatrick   // Consumes types defined via decltype keyword.
158061da546Spatrick   bool ConsumeDecltype();
159061da546Spatrick 
160061da546Spatrick   // Skips 'const' and 'volatile'
161061da546Spatrick   void SkipPtrsAndRefs();
162061da546Spatrick 
163061da546Spatrick   // Consumes things like 'const * const &'
164061da546Spatrick   bool ConsumePtrsAndRefs();
165061da546Spatrick 
166061da546Spatrick   // Consumes full type name like 'Namespace::Class<int>::Method()::InnerClass'
167061da546Spatrick   bool ConsumeTypename();
168061da546Spatrick 
169*f6aab3d8Srobert   /// Consumes ABI tags enclosed within '[abi:' ... ']'
170*f6aab3d8Srobert   ///
171*f6aab3d8Srobert   /// Since there is no restriction on what the ABI tag
172*f6aab3d8Srobert   /// string may contain, this API supports parsing a small
173*f6aab3d8Srobert   /// set of special characters.
174*f6aab3d8Srobert   ///
175*f6aab3d8Srobert   /// The following regex describes the set of supported characters:
176*f6aab3d8Srobert   ///   [A-Za-z,.\s\d]+
177*f6aab3d8Srobert   bool ConsumeAbiTag();
178*f6aab3d8Srobert 
179*f6aab3d8Srobert   std::optional<ParsedNameRanges> ParseFullNameImpl();
180061da546Spatrick   llvm::StringRef GetTextForRange(const Range &range);
181061da546Spatrick 
182061da546Spatrick   // Populate m_tokens by calling clang lexer on m_text.
183061da546Spatrick   void ExtractTokens();
184061da546Spatrick };
185061da546Spatrick 
186061da546Spatrick } // namespace lldb_private
187061da546Spatrick 
188dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H
189