1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
//===--- 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
|