| //===- 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/Optional.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/ADT/StringRef.h" |
| #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 Optional<MatcherCtor>() if not |
| /// found. |
| virtual llvm::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; |
| |
| llvm::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 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); |
| } |
| |
| /// 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, |
| llvm::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_AST_MATCHERS_DYNAMIC_PARSER_H |