//===--- 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: // := | // := "quoted string" // := () // := [a-zA-Z]+ // := | , // //===----------------------------------------------------------------------===// #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 #include 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::ArrayRef args, Diagnostics *error) = 0; // Look up a matcher by name in the matcher name found by the parser. virtual std::optional lookupMatcherCtor(llvm::StringRef matcherName) = 0; // Compute the list of completion types for Context. virtual std::vector getAcceptedCompletionTypes( llvm::ArrayRef> Context); // Compute the list of completions that match any of acceptedTypes. virtual std::vector getMatcherCompletions(llvm::ArrayRef 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 lookupMatcherCtor(llvm::StringRef matcherName) override; VariantMatcher actOnMatcherExpression(MatcherCtor ctor, SourceRange nameRange, llvm::ArrayRef args, Diagnostics *error) override; std::vector getAcceptedCompletionTypes( llvm::ArrayRef> context) override; std::vector getMatcherCompletions(llvm::ArrayRef acceptedTypes) override; private: const Registry &matcherRegistry; }; using NamedValueMap = llvm::StringMap; // Methods to parse a matcher expression and return a DynMatcher object, // transferring ownership to the caller. static std::optional parseMatcherExpression(llvm::StringRef &matcherCode, const Registry &matcherRegistry, const NamedValueMap *namedValues, Diagnostics *error); static std::optional 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 completeExpression(llvm::StringRef &code, unsigned completionOffset, const Registry &matcherRegistry, const NamedValueMap *namedValues); static std::vector 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 parseExpressionImpl(VariantValue *value); bool parseMatcherArgs(std::vector &args, MatcherCtor ctor, const TokenInfo &nameToken, TokenInfo &endToken); bool parseMatcherExpressionImpl(const TokenInfo &nameToken, const TokenInfo &openToken, std::optional ctor, VariantValue *value); bool parseIdentifierPrefixImpl(VariantValue *value); void addCompletion(const TokenInfo &compToken, const MatcherCompletion &completion); void addExpressionCompletions(); std::vector getNamedValueCompletions(llvm::ArrayRef acceptedTypes); CodeTokenizer *const tokenizer; std::unique_ptr sema; const NamedValueMap *const namedValues; Diagnostics *const error; using ContextStackTy = std::vector>; ContextStackTy contextStack; std::vector completions; }; } // namespace mlir::query::matcher::internal #endif // MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H