194 lines · c
1//===--- Parser.h - Matcher expression parser -------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Simple matcher expression parser.10//11// This file contains the Parser class, which is responsible for parsing12// expressions in a specific format: matcherName(Arg0, Arg1, ..., ArgN). The13// parser can also interpret simple types, like strings.14//15// The actual processing of the matchers is handled by a Sema object that is16// provided to the parser.17//18// The grammar for the supported expressions is as follows:19// <Expression> := <Literal> | <MatcherExpression>20// <Literal> := <StringLiteral> | <NumericLiteral> | <BooleanLiteral>21// <StringLiteral> := "quoted string"22// <BooleanLiteral> := "true" | "false"23// <NumericLiteral> := [0-9]+24// <MatcherExpression> := <MatcherName>(<ArgumentList>)25// <MatcherName> := [a-zA-Z]+26// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>27//28//===----------------------------------------------------------------------===//29 30#ifndef MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H31#define MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H32 33#include "Diagnostics.h"34#include "RegistryManager.h"35#include "llvm/ADT/ArrayRef.h"36#include "llvm/ADT/StringMap.h"37#include "llvm/ADT/StringRef.h"38#include <memory>39#include <vector>40 41namespace mlir::query::matcher::internal {42 43// Matcher expression parser.44class Parser {45public:46 // Different possible tokens.47 enum class TokenKind {48 Eof,49 NewLine,50 OpenParen,51 CloseParen,52 Comma,53 Period,54 Literal,55 Ident,56 InvalidChar,57 CodeCompletion,58 Error59 };60 61 // Interface to connect the parser with the registry and more. The parser uses62 // the Sema instance passed into parseMatcherExpression() to handle all63 // matcher tokens.64 class Sema {65 public:66 virtual ~Sema();67 68 // Process a matcher expression. The caller takes ownership of the Matcher69 // object returned.70 virtual VariantMatcher actOnMatcherExpression(71 MatcherCtor ctor, SourceRange nameRange, llvm::StringRef functionName,72 llvm::ArrayRef<ParserValue> args, Diagnostics *error) = 0;73 74 // Look up a matcher by name in the matcher name found by the parser.75 virtual std::optional<MatcherCtor>76 lookupMatcherCtor(llvm::StringRef matcherName) = 0;77 78 // Compute the list of completion types for Context.79 virtual std::vector<ArgKind> getAcceptedCompletionTypes(80 llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);81 82 // Compute the list of completions that match any of acceptedTypes.83 virtual std::vector<MatcherCompletion>84 getMatcherCompletions(llvm::ArrayRef<ArgKind> acceptedTypes);85 };86 87 // An implementation of the Sema interface that uses the matcher registry to88 // process tokens.89 class RegistrySema : public Parser::Sema {90 public:91 RegistrySema(const Registry &matcherRegistry)92 : matcherRegistry(matcherRegistry) {}93 ~RegistrySema() override;94 95 std::optional<MatcherCtor>96 lookupMatcherCtor(llvm::StringRef matcherName) override;97 98 VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,99 SourceRange NameRange,100 StringRef functionName,101 ArrayRef<ParserValue> Args,102 Diagnostics *Error) override;103 104 std::vector<ArgKind> getAcceptedCompletionTypes(105 llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> context) override;106 107 std::vector<MatcherCompletion>108 getMatcherCompletions(llvm::ArrayRef<ArgKind> acceptedTypes) override;109 110 private:111 const Registry &matcherRegistry;112 };113 114 using NamedValueMap = llvm::StringMap<VariantValue>;115 116 // Methods to parse a matcher expression and return a DynMatcher object,117 // transferring ownership to the caller.118 static std::optional<DynMatcher>119 parseMatcherExpression(llvm::StringRef &matcherCode,120 const Registry &matcherRegistry,121 const NamedValueMap *namedValues, Diagnostics *error);122 static std::optional<DynMatcher>123 parseMatcherExpression(llvm::StringRef &matcherCode,124 const Registry &matcherRegistry, Diagnostics *error) {125 return parseMatcherExpression(matcherCode, matcherRegistry, nullptr, error);126 }127 128 // Methods to parse any expression supported by this parser.129 static bool parseExpression(llvm::StringRef &code,130 const Registry &matcherRegistry,131 const NamedValueMap *namedValues,132 VariantValue *value, Diagnostics *error);133 134 static bool parseExpression(llvm::StringRef &code,135 const Registry &matcherRegistry,136 VariantValue *value, Diagnostics *error) {137 return parseExpression(code, matcherRegistry, nullptr, value, error);138 }139 140 // Methods to complete an expression at a given offset.141 static std::vector<MatcherCompletion>142 completeExpression(llvm::StringRef &code, unsigned completionOffset,143 const Registry &matcherRegistry,144 const NamedValueMap *namedValues);145 static std::vector<MatcherCompletion>146 completeExpression(llvm::StringRef &code, unsigned completionOffset,147 const Registry &matcherRegistry) {148 return completeExpression(code, completionOffset, matcherRegistry, nullptr);149 }150 151private:152 class CodeTokenizer;153 struct ScopedContextEntry;154 struct TokenInfo;155 156 Parser(CodeTokenizer *tokenizer, const Registry &matcherRegistry,157 const NamedValueMap *namedValues, Diagnostics *error);158 159 bool parseChainedExpression(std::string &argument);160 161 bool parseExpressionImpl(VariantValue *value);162 163 bool parseMatcherArgs(std::vector<ParserValue> &args, MatcherCtor ctor,164 const TokenInfo &nameToken, TokenInfo &endToken);165 166 bool parseMatcherExpressionImpl(const TokenInfo &nameToken,167 const TokenInfo &openToken,168 std::optional<MatcherCtor> ctor,169 VariantValue *value);170 171 bool parseIdentifierPrefixImpl(VariantValue *value);172 173 void addCompletion(const TokenInfo &compToken,174 const MatcherCompletion &completion);175 void addExpressionCompletions();176 177 std::vector<MatcherCompletion>178 getNamedValueCompletions(llvm::ArrayRef<ArgKind> acceptedTypes);179 180 CodeTokenizer *const tokenizer;181 std::unique_ptr<RegistrySema> sema;182 const NamedValueMap *const namedValues;183 Diagnostics *const error;184 185 using ContextStackTy = std::vector<std::pair<MatcherCtor, unsigned>>;186 187 ContextStackTy contextStack;188 std::vector<MatcherCompletion> completions;189};190 191} // namespace mlir::query::matcher::internal192 193#endif // MLIR_TOOLS_MLIRQUERY_MATCHER_PARSER_H194