You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.2 KiB
177 lines
5.2 KiB
//===-- CPlusPlusNameParser.h -----------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H
|
|
#define LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H
|
|
|
|
#include "clang/Lex/Lexer.h"
|
|
#include "llvm/ADT/Optional.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "lldb/Utility/ConstString.h"
|
|
#include "lldb/lldb-private.h"
|
|
|
|
namespace lldb_private {
|
|
|
|
// Helps to validate and obtain various parts of C++ definitions.
|
|
class CPlusPlusNameParser {
|
|
public:
|
|
CPlusPlusNameParser(llvm::StringRef text) : m_text(text) { ExtractTokens(); }
|
|
|
|
struct ParsedName {
|
|
llvm::StringRef basename;
|
|
llvm::StringRef context;
|
|
};
|
|
|
|
struct ParsedFunction {
|
|
ParsedName name;
|
|
llvm::StringRef arguments;
|
|
llvm::StringRef qualifiers;
|
|
};
|
|
|
|
// Treats given text as a function definition and parses it.
|
|
// Function definition might or might not have a return type and this should
|
|
// change parsing result.
|
|
// Examples:
|
|
// main(int, chat const*)
|
|
// T fun(int, bool)
|
|
// std::vector<int>::push_back(int)
|
|
// int& map<int, pair<short, int>>::operator[](short) const
|
|
// int (*get_function(const chat *))()
|
|
llvm::Optional<ParsedFunction> ParseAsFunctionDefinition();
|
|
|
|
// Treats given text as a potentially nested name of C++ entity (function,
|
|
// class, field) and parses it.
|
|
// Examples:
|
|
// main
|
|
// fun
|
|
// std::vector<int>::push_back
|
|
// map<int, pair<short, int>>::operator[]
|
|
// func<C>(int, C&)::nested_class::method
|
|
llvm::Optional<ParsedName> ParseAsFullName();
|
|
|
|
private:
|
|
// A C++ definition to parse.
|
|
llvm::StringRef m_text;
|
|
// Tokens extracted from m_text.
|
|
llvm::SmallVector<clang::Token, 30> m_tokens;
|
|
// Index of the next token to look at from m_tokens.
|
|
size_t m_next_token_index = 0;
|
|
|
|
// Range of tokens saved in m_next_token_index.
|
|
struct Range {
|
|
size_t begin_index = 0;
|
|
size_t end_index = 0;
|
|
|
|
Range() {}
|
|
Range(size_t begin, size_t end) : begin_index(begin), end_index(end) {
|
|
assert(end >= begin);
|
|
}
|
|
|
|
size_t size() const { return end_index - begin_index; }
|
|
|
|
bool empty() const { return size() == 0; }
|
|
};
|
|
|
|
struct ParsedNameRanges {
|
|
Range basename_range;
|
|
Range context_range;
|
|
};
|
|
|
|
// Bookmark automatically restores parsing position (m_next_token_index)
|
|
// when destructed unless it's manually removed with Remove().
|
|
class Bookmark {
|
|
public:
|
|
Bookmark(size_t &position)
|
|
: m_position(position), m_position_value(position) {}
|
|
Bookmark(const Bookmark &) = delete;
|
|
Bookmark(Bookmark &&b)
|
|
: m_position(b.m_position), m_position_value(b.m_position_value),
|
|
m_restore(b.m_restore) {
|
|
b.Remove();
|
|
}
|
|
Bookmark &operator=(Bookmark &&) = delete;
|
|
Bookmark &operator=(const Bookmark &) = delete;
|
|
|
|
void Remove() { m_restore = false; }
|
|
size_t GetSavedPosition() { return m_position_value; }
|
|
~Bookmark() {
|
|
if (m_restore) {
|
|
m_position = m_position_value;
|
|
}
|
|
}
|
|
|
|
private:
|
|
size_t &m_position;
|
|
size_t m_position_value;
|
|
bool m_restore = true;
|
|
};
|
|
|
|
bool HasMoreTokens();
|
|
void Advance();
|
|
void TakeBack();
|
|
bool ConsumeToken(clang::tok::TokenKind kind);
|
|
template <typename... Ts> bool ConsumeToken(Ts... kinds);
|
|
Bookmark SetBookmark();
|
|
size_t GetCurrentPosition();
|
|
clang::Token &Peek();
|
|
bool ConsumeBrackets(clang::tok::TokenKind left, clang::tok::TokenKind right);
|
|
|
|
llvm::Optional<ParsedFunction> ParseFunctionImpl(bool expect_return_type);
|
|
|
|
// Parses functions returning function pointers 'string (*f(int x))(float y)'
|
|
llvm::Optional<ParsedFunction> ParseFuncPtr(bool expect_return_type);
|
|
|
|
// Consumes function arguments enclosed within '(' ... ')'
|
|
bool ConsumeArguments();
|
|
|
|
// Consumes template arguments enclosed within '<' ... '>'
|
|
bool ConsumeTemplateArgs();
|
|
|
|
// Consumes '(anonymous namespace)'
|
|
bool ConsumeAnonymousNamespace();
|
|
|
|
// Consumes '{lambda ...}'
|
|
bool ConsumeLambda();
|
|
|
|
// Consumes operator declaration like 'operator *' or 'operator delete []'
|
|
bool ConsumeOperator();
|
|
|
|
// Skips 'const' and 'volatile'
|
|
void SkipTypeQualifiers();
|
|
|
|
// Skips 'const', 'volatile', '&', '&&' in the end of the function.
|
|
void SkipFunctionQualifiers();
|
|
|
|
// Consumes built-in types like 'int' or 'unsigned long long int'
|
|
bool ConsumeBuiltinType();
|
|
|
|
// Consumes types defined via decltype keyword.
|
|
bool ConsumeDecltype();
|
|
|
|
// Skips 'const' and 'volatile'
|
|
void SkipPtrsAndRefs();
|
|
|
|
// Consumes things like 'const * const &'
|
|
bool ConsumePtrsAndRefs();
|
|
|
|
// Consumes full type name like 'Namespace::Class<int>::Method()::InnerClass'
|
|
bool ConsumeTypename();
|
|
|
|
llvm::Optional<ParsedNameRanges> ParseFullNameImpl();
|
|
llvm::StringRef GetTextForRange(const Range &range);
|
|
|
|
// Populate m_tokens by calling clang lexer on m_text.
|
|
void ExtractTokens();
|
|
};
|
|
|
|
} // namespace lldb_private
|
|
|
|
#endif // LLDB_SOURCE_PLUGINS_LANGUAGE_CPLUSPLUS_CPLUSPLUSNAMEPARSER_H
|