| //===--- 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 |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Simple matcher expression parser. |
| // |
| // This file contains the Parser class, which is responsible for parsing |
| // expressions in a specific format: matcherName(Arg0, Arg1, ..., ArgN). The |
| // parser can also interpret simple types, like strings. |
| // |
| // The actual processing of the matchers is handled by a Sema object that is |
| // provided to the parser. |
| // |
| // The grammar for the supported expressions is as follows: |
| // <Expression> := <Literal> | <MatcherExpression> |
| // <Literal> := <StringLiteral> | <NumericLiteral> | <BooleanLiteral> |
| // <StringLiteral> := "quoted string" |
| // <BooleanLiteral> := "true" | "false" |
| // <NumericLiteral> := [0-9]+ |
| // <MatcherExpression> := <MatcherName>(<ArgumentList>) |
| // <MatcherName> := [a-zA-Z]+ |
| // <ArgumentList> := <Expression> | <Expression>,<ArgumentList> |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H |
| #define MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H |
| |
| #include "Diagnostics.h" |
| #include "RegistryManager.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/ADT/StringRef.h" |
| #include <memory> |
| #include <vector> |
| |
| namespace mlir::query::matcher::internal { |
| |
| // Matcher expression parser. |
| class Parser { |
| public: |
| // Different possible tokens. |
| enum class TokenKind { |
| Eof, |
| NewLine, |
| OpenParen, |
| CloseParen, |
| Comma, |
| Period, |
| Literal, |
| Ident, |
| InvalidChar, |
| CodeCompletion, |
| Error |
| }; |
| |
| // Interface to connect the parser with the registry and more. The parser uses |
| // the Sema instance passed into parseMatcherExpression() to handle all |
| // matcher tokens. |
| class Sema { |
| public: |
| virtual ~Sema(); |
| |
| // Process a matcher expression. The caller takes ownership of the Matcher |
| // object returned. |
| virtual VariantMatcher actOnMatcherExpression( |
| MatcherCtor ctor, SourceRange nameRange, llvm::StringRef functionName, |
| llvm::ArrayRef<ParserValue> args, Diagnostics *error) = 0; |
| |
| // Look up a matcher by name in the matcher name found by the parser. |
| virtual std::optional<MatcherCtor> |
| lookupMatcherCtor(llvm::StringRef matcherName) = 0; |
| |
| // Compute the list of completion types for Context. |
| virtual std::vector<ArgKind> getAcceptedCompletionTypes( |
| llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context); |
| |
| // Compute the list of completions that match any of acceptedTypes. |
| virtual std::vector<MatcherCompletion> |
| getMatcherCompletions(llvm::ArrayRef<ArgKind> acceptedTypes); |
| }; |
| |
| // An implementation of the Sema interface that uses the matcher registry to |
| // process tokens. |
| class RegistrySema : public Parser::Sema { |
| public: |
| RegistrySema(const Registry &matcherRegistry) |
| : matcherRegistry(matcherRegistry) {} |
| ~RegistrySema() override; |
| |
| std::optional<MatcherCtor> |
| lookupMatcherCtor(llvm::StringRef matcherName) override; |
| |
| VariantMatcher actOnMatcherExpression(MatcherCtor Ctor, |
| SourceRange NameRange, |
| StringRef functionName, |
| 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; |
| |
| private: |
| const Registry &matcherRegistry; |
| }; |
| |
| using NamedValueMap = llvm::StringMap<VariantValue>; |
| |
| // Methods to parse a matcher expression and return a DynMatcher object, |
| // transferring ownership to the caller. |
| static std::optional<DynMatcher> |
| parseMatcherExpression(llvm::StringRef &matcherCode, |
| const Registry &matcherRegistry, |
| const NamedValueMap *namedValues, Diagnostics *error); |
| static std::optional<DynMatcher> |
| parseMatcherExpression(llvm::StringRef &matcherCode, |
| const Registry &matcherRegistry, Diagnostics *error) { |
| return parseMatcherExpression(matcherCode, matcherRegistry, nullptr, error); |
| } |
| |
| // Methods to parse any expression supported by this parser. |
| static bool parseExpression(llvm::StringRef &code, |
| const Registry &matcherRegistry, |
| const NamedValueMap *namedValues, |
| VariantValue *value, Diagnostics *error); |
| |
| static bool parseExpression(llvm::StringRef &code, |
| const Registry &matcherRegistry, |
| VariantValue *value, Diagnostics *error) { |
| return parseExpression(code, matcherRegistry, nullptr, value, error); |
| } |
| |
| // Methods to complete an expression at a given offset. |
| static std::vector<MatcherCompletion> |
| completeExpression(llvm::StringRef &code, unsigned completionOffset, |
| const Registry &matcherRegistry, |
| const NamedValueMap *namedValues); |
| static std::vector<MatcherCompletion> |
| completeExpression(llvm::StringRef &code, unsigned completionOffset, |
| const Registry &matcherRegistry) { |
| return completeExpression(code, completionOffset, matcherRegistry, nullptr); |
| } |
| |
| private: |
| class CodeTokenizer; |
| struct ScopedContextEntry; |
| struct TokenInfo; |
| |
| Parser(CodeTokenizer *tokenizer, const Registry &matcherRegistry, |
| const NamedValueMap *namedValues, Diagnostics *error); |
| |
| bool parseChainedExpression(std::string &argument); |
| |
| bool parseExpressionImpl(VariantValue *value); |
| |
| bool parseMatcherArgs(std::vector<ParserValue> &args, MatcherCtor ctor, |
| const TokenInfo &nameToken, TokenInfo &endToken); |
| |
| 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(llvm::ArrayRef<ArgKind> acceptedTypes); |
| |
| CodeTokenizer *const tokenizer; |
| std::unique_ptr<RegistrySema> sema; |
| const NamedValueMap *const namedValues; |
| Diagnostics *const error; |
| |
| using ContextStackTy = std::vector<std::pair<MatcherCtor, unsigned>>; |
| |
| ContextStackTy contextStack; |
| std::vector<MatcherCompletion> completions; |
| }; |
| |
| } // namespace mlir::query::matcher::internal |
| |
| #endif // MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H |