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