clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
284 lines
11 KiB
C++
284 lines
11 KiB
C++
//===- Parser.h - Matcher expression parser ---------------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
/// \file
|
|
/// Simple matcher expression parser.
|
|
///
|
|
/// The parser understands matcher expressions of the form:
|
|
/// MatcherName(Arg0, Arg1, ..., ArgN)
|
|
/// as well as simple types like strings.
|
|
/// The parser does not know how to process the matchers. It delegates this task
|
|
/// to a Sema object received as an argument.
|
|
///
|
|
/// \code
|
|
/// Grammar for the expressions supported:
|
|
/// <Expression> := <Literal> | <NamedValue> | <MatcherExpression>
|
|
/// <Literal> := <StringLiteral> | <Boolean> | <Double> | <Unsigned>
|
|
/// <StringLiteral> := "quoted string"
|
|
/// <Boolean> := true | false
|
|
/// <Double> := [0-9]+.[0-9]* | [0-9]+.[0-9]*[eE][-+]?[0-9]+
|
|
/// <Unsigned> := [0-9]+
|
|
/// <NamedValue> := <Identifier>
|
|
/// <MatcherExpression> := <Identifier>(<ArgumentList>) |
|
|
/// <Identifier>(<ArgumentList>).bind(<StringLiteral>)
|
|
/// <Identifier> := [a-zA-Z]+
|
|
/// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>
|
|
/// \endcode
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
|
|
#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
|
|
|
|
#include "clang/ASTMatchers/ASTMatchersInternal.h"
|
|
#include "clang/ASTMatchers/Dynamic/Registry.h"
|
|
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include <optional>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace clang {
|
|
namespace ast_matchers {
|
|
namespace dynamic {
|
|
|
|
class Diagnostics;
|
|
|
|
/// Matcher expression parser.
|
|
class Parser {
|
|
public:
|
|
/// Interface to connect the parser with the registry and more.
|
|
///
|
|
/// The parser uses the Sema instance passed into
|
|
/// parseMatcherExpression() to handle all matcher tokens. The simplest
|
|
/// processor implementation would simply call into the registry to create
|
|
/// the matchers.
|
|
/// However, a more complex processor might decide to intercept the matcher
|
|
/// creation and do some extra work. For example, it could apply some
|
|
/// transformation to the matcher by adding some id() nodes, or could detect
|
|
/// specific matcher nodes for more efficient lookup.
|
|
class Sema {
|
|
public:
|
|
virtual ~Sema();
|
|
|
|
/// Process a matcher expression.
|
|
///
|
|
/// All the arguments passed here have already been processed.
|
|
///
|
|
/// \param Ctor A matcher constructor looked up by lookupMatcherCtor.
|
|
///
|
|
/// \param NameRange The location of the name in the matcher source.
|
|
/// Useful for error reporting.
|
|
///
|
|
/// \param BindID The ID to use to bind the matcher, or a null \c StringRef
|
|
/// if no ID is specified.
|
|
///
|
|
/// \param Args The argument list for the matcher.
|
|
///
|
|
/// \return The matcher objects constructed by the processor, or a null
|
|
/// matcher if an error occurred. In that case, \c Error will contain a
|
|
/// description of the error.
|
|
virtual VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
|
|
SourceRange NameRange,
|
|
StringRef BindID,
|
|
ArrayRef<ParserValue> Args,
|
|
Diagnostics *Error) = 0;
|
|
|
|
/// Look up a matcher by name.
|
|
///
|
|
/// \param MatcherName The matcher name found by the parser.
|
|
///
|
|
/// \return The matcher constructor, or std::optional<MatcherCtor>() if not
|
|
/// found.
|
|
virtual std::optional<MatcherCtor>
|
|
lookupMatcherCtor(StringRef MatcherName) = 0;
|
|
|
|
virtual bool isBuilderMatcher(MatcherCtor) const = 0;
|
|
|
|
virtual ASTNodeKind nodeMatcherType(MatcherCtor) const = 0;
|
|
|
|
virtual internal::MatcherDescriptorPtr
|
|
buildMatcherCtor(MatcherCtor, SourceRange NameRange,
|
|
ArrayRef<ParserValue> Args, Diagnostics *Error) const = 0;
|
|
|
|
/// Compute the list of completion types for \p Context.
|
|
///
|
|
/// Each element of \p Context represents a matcher invocation, going from
|
|
/// outermost to innermost. Elements are pairs consisting of a reference to
|
|
/// the matcher constructor and the index of the next element in the
|
|
/// argument list of that matcher (or for the last element, the index of
|
|
/// the completion point in the argument list). An empty list requests
|
|
/// completion for the root matcher.
|
|
virtual std::vector<ArgKind> getAcceptedCompletionTypes(
|
|
llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
|
|
|
|
/// Compute the list of completions that match any of
|
|
/// \p AcceptedTypes.
|
|
///
|
|
/// \param AcceptedTypes All types accepted for this completion.
|
|
///
|
|
/// \return All completions for the specified types.
|
|
/// Completions should be valid when used in \c lookupMatcherCtor().
|
|
/// The matcher constructed from the return of \c lookupMatcherCtor()
|
|
/// should be convertible to some type in \p AcceptedTypes.
|
|
virtual std::vector<MatcherCompletion>
|
|
getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes);
|
|
};
|
|
|
|
/// Sema implementation that uses the matcher registry to process the
|
|
/// tokens.
|
|
class RegistrySema : public Parser::Sema {
|
|
public:
|
|
~RegistrySema() override;
|
|
|
|
std::optional<MatcherCtor>
|
|
lookupMatcherCtor(StringRef MatcherName) override;
|
|
|
|
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
|
|
SourceRange NameRange,
|
|
StringRef BindID,
|
|
ArrayRef<ParserValue> Args,
|
|
Diagnostics *Error) override;
|
|
|
|
std::vector<ArgKind> getAcceptedCompletionTypes(
|
|
llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) override;
|
|
|
|
bool isBuilderMatcher(MatcherCtor Ctor) const override;
|
|
|
|
ASTNodeKind nodeMatcherType(MatcherCtor) const override;
|
|
|
|
internal::MatcherDescriptorPtr
|
|
buildMatcherCtor(MatcherCtor, SourceRange NameRange,
|
|
ArrayRef<ParserValue> Args,
|
|
Diagnostics *Error) const override;
|
|
|
|
std::vector<MatcherCompletion>
|
|
getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override;
|
|
};
|
|
|
|
using NamedValueMap = llvm::StringMap<VariantValue>;
|
|
|
|
/// Parse a matcher expression.
|
|
///
|
|
/// \param MatcherCode The matcher expression to parse.
|
|
///
|
|
/// \param S The Sema instance that will help the parser
|
|
/// construct the matchers. If null, it uses the default registry.
|
|
///
|
|
/// \param NamedValues A map of precomputed named values. This provides
|
|
/// the dictionary for the <NamedValue> rule of the grammar.
|
|
/// If null, it is ignored.
|
|
///
|
|
/// \return The matcher object constructed by the processor, or an empty
|
|
/// Optional if an error occurred. In that case, \c Error will contain a
|
|
/// description of the error.
|
|
/// The caller takes ownership of the DynTypedMatcher object returned.
|
|
static std::optional<DynTypedMatcher>
|
|
parseMatcherExpression(StringRef &MatcherCode, Sema *S,
|
|
const NamedValueMap *NamedValues, Diagnostics *Error);
|
|
static std::optional<DynTypedMatcher>
|
|
parseMatcherExpression(StringRef &MatcherCode, Sema *S, Diagnostics *Error) {
|
|
return parseMatcherExpression(MatcherCode, S, nullptr, Error);
|
|
}
|
|
static std::optional<DynTypedMatcher>
|
|
parseMatcherExpression(StringRef &MatcherCode, Diagnostics *Error) {
|
|
return parseMatcherExpression(MatcherCode, nullptr, Error);
|
|
}
|
|
|
|
/// Parse an expression.
|
|
///
|
|
/// Parses any expression supported by this parser. In general, the
|
|
/// \c parseMatcherExpression function is a better approach to get a matcher
|
|
/// object.
|
|
///
|
|
/// \param S The Sema instance that will help the parser
|
|
/// construct the matchers. If null, it uses the default registry.
|
|
///
|
|
/// \param NamedValues A map of precomputed named values. This provides
|
|
/// the dictionary for the <NamedValue> rule of the grammar.
|
|
/// If null, it is ignored.
|
|
static bool parseExpression(StringRef &Code, Sema *S,
|
|
const NamedValueMap *NamedValues,
|
|
VariantValue *Value, Diagnostics *Error);
|
|
static bool parseExpression(StringRef &Code, Sema *S, VariantValue *Value,
|
|
Diagnostics *Error) {
|
|
return parseExpression(Code, S, nullptr, Value, Error);
|
|
}
|
|
static bool parseExpression(StringRef &Code, VariantValue *Value,
|
|
Diagnostics *Error) {
|
|
return parseExpression(Code, nullptr, Value, Error);
|
|
}
|
|
|
|
/// Complete an expression at the given offset.
|
|
///
|
|
/// \param S The Sema instance that will help the parser
|
|
/// construct the matchers. If null, it uses the default registry.
|
|
///
|
|
/// \param NamedValues A map of precomputed named values. This provides
|
|
/// the dictionary for the <NamedValue> rule of the grammar.
|
|
/// If null, it is ignored.
|
|
///
|
|
/// \return The list of completions, which may be empty if there are no
|
|
/// available completions or if an error occurred.
|
|
static std::vector<MatcherCompletion>
|
|
completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S,
|
|
const NamedValueMap *NamedValues);
|
|
static std::vector<MatcherCompletion>
|
|
completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S) {
|
|
return completeExpression(Code, CompletionOffset, S, nullptr);
|
|
}
|
|
static std::vector<MatcherCompletion>
|
|
completeExpression(StringRef &Code, unsigned CompletionOffset) {
|
|
return completeExpression(Code, CompletionOffset, nullptr);
|
|
}
|
|
|
|
private:
|
|
class CodeTokenizer;
|
|
struct ScopedContextEntry;
|
|
struct TokenInfo;
|
|
|
|
Parser(CodeTokenizer *Tokenizer, Sema *S,
|
|
const NamedValueMap *NamedValues,
|
|
Diagnostics *Error);
|
|
|
|
bool parseBindID(std::string &BindID);
|
|
bool parseExpressionImpl(VariantValue *Value);
|
|
bool parseMatcherBuilder(MatcherCtor Ctor, const TokenInfo &NameToken,
|
|
const TokenInfo &OpenToken, VariantValue *Value);
|
|
bool parseMatcherExpressionImpl(const TokenInfo &NameToken,
|
|
const TokenInfo &OpenToken,
|
|
std::optional<MatcherCtor> Ctor,
|
|
VariantValue *Value);
|
|
bool parseIdentifierPrefixImpl(VariantValue *Value);
|
|
|
|
void addCompletion(const TokenInfo &CompToken,
|
|
const MatcherCompletion &Completion);
|
|
void addExpressionCompletions();
|
|
|
|
std::vector<MatcherCompletion>
|
|
getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes);
|
|
|
|
CodeTokenizer *const Tokenizer;
|
|
Sema *const S;
|
|
const NamedValueMap *const NamedValues;
|
|
Diagnostics *const Error;
|
|
|
|
using ContextStackTy = std::vector<std::pair<MatcherCtor, unsigned>>;
|
|
|
|
ContextStackTy ContextStack;
|
|
std::vector<MatcherCompletion> Completions;
|
|
};
|
|
|
|
} // namespace dynamic
|
|
} // namespace ast_matchers
|
|
} // namespace clang
|
|
|
|
#endif // LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
|