blob: cdc259e0d045d63aacf1371c294d3c9ae82486e3 [file] [log] [blame]
//===--- Parser.h - Matcher expression parser -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief 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> | <Unsigned>
/// <StringLiteral> := "quoted string"
/// <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/Dynamic/Diagnostics.h"
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
namespace ast_matchers {
namespace dynamic {
/// \brief Matcher expression parser.
class Parser {
public:
/// \brief 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();
/// \brief 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,
const SourceRange &NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) = 0;
/// \brief Look up a matcher by name.
///
/// \param MatcherName The matcher name found by the parser.
///
/// \return The matcher constructor, or Optional<MatcherCtor>() if not
/// found.
virtual llvm::Optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName) = 0;
/// \brief 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);
/// \brief 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);
};
/// \brief Sema implementation that uses the matcher registry to process the
/// tokens.
class RegistrySema : public Parser::Sema {
public:
~RegistrySema() override;
llvm::Optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName) override;
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
const SourceRange &NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) override;
std::vector<ArgKind> getAcceptedCompletionTypes(
llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) override;
std::vector<MatcherCompletion>
getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override;
};
typedef llvm::StringMap<VariantValue> NamedValueMap;
/// \brief 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 llvm::Optional<DynTypedMatcher>
parseMatcherExpression(StringRef MatcherCode, Sema *S,
const NamedValueMap *NamedValues,
Diagnostics *Error);
static llvm::Optional<DynTypedMatcher>
parseMatcherExpression(StringRef MatcherCode, Sema *S,
Diagnostics *Error) {
return parseMatcherExpression(MatcherCode, S, nullptr, Error);
}
static llvm::Optional<DynTypedMatcher>
parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error) {
return parseMatcherExpression(MatcherCode, nullptr, Error);
}
/// \brief 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);
}
/// \brief 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 parseExpressionImpl(VariantValue *Value);
bool parseMatcherExpressionImpl(const TokenInfo &NameToken,
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;
typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy;
ContextStackTy ContextStack;
std::vector<MatcherCompletion> Completions;
};
} // namespace dynamic
} // namespace ast_matchers
} // namespace clang
#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H