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