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