Parser.h
10.6 KB
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
//===- Parser.h - MLIR Base Parser Class ------------------------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_LIB_PARSER_PARSER_H
#define MLIR_LIB_PARSER_PARSER_H
#include "ParserState.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/OpImplementation.h"
namespace mlir {
namespace detail {
//===----------------------------------------------------------------------===//
// Parser
//===----------------------------------------------------------------------===//
/// This class implement support for parsing global entities like attributes and
/// types. It is intended to be subclassed by specialized subparsers that
/// include state.
class Parser {
public:
Builder builder;
Parser(ParserState &state) : builder(state.context), state(state) {}
// Helper methods to get stuff from the parser-global state.
ParserState &getState() const { return state; }
MLIRContext *getContext() const { return state.context; }
const llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
/// Parse a comma-separated list of elements up until the specified end token.
ParseResult
parseCommaSeparatedListUntil(Token::Kind rightToken,
const std::function<ParseResult()> &parseElement,
bool allowEmptyList = true);
/// Parse a comma separated list of elements that must have at least one entry
/// in it.
ParseResult
parseCommaSeparatedList(const std::function<ParseResult()> &parseElement);
ParseResult parsePrettyDialectSymbolName(StringRef &prettyName);
// We have two forms of parsing methods - those that return a non-null
// pointer on success, and those that return a ParseResult to indicate whether
// they returned a failure. The second class fills in by-reference arguments
// as the results of their action.
//===--------------------------------------------------------------------===//
// Error Handling
//===--------------------------------------------------------------------===//
/// Emit an error and return failure.
InFlightDiagnostic emitError(const Twine &message = {}) {
return emitError(state.curToken.getLoc(), message);
}
InFlightDiagnostic emitError(llvm::SMLoc loc, const Twine &message = {});
/// Encode the specified source location information into an attribute for
/// attachment to the IR.
Location getEncodedSourceLocation(llvm::SMLoc loc) {
// If there are no active nested parsers, we can get the encoded source
// location directly.
if (state.parserDepth == 0)
return state.lex.getEncodedSourceLocation(loc);
// Otherwise, we need to re-encode it to point to the top level buffer.
return state.symbols.topLevelLexer->getEncodedSourceLocation(
remapLocationToTopLevelBuffer(loc));
}
/// Remaps the given SMLoc to the top level lexer of the parser. This is used
/// to adjust locations of potentially nested parsers to ensure that they can
/// be emitted properly as diagnostics.
llvm::SMLoc remapLocationToTopLevelBuffer(llvm::SMLoc loc) {
// If there are no active nested parsers, we can return location directly.
SymbolState &symbols = state.symbols;
if (state.parserDepth == 0)
return loc;
assert(symbols.topLevelLexer && "expected valid top-level lexer");
// Otherwise, we need to remap the location to the main parser. This is
// simply offseting the location onto the location of the last nested
// parser.
size_t offset = loc.getPointer() - state.lex.getBufferBegin();
auto *rawLoc =
symbols.nestedParserLocs[state.parserDepth - 1].getPointer() + offset;
return llvm::SMLoc::getFromPointer(rawLoc);
}
//===--------------------------------------------------------------------===//
// Token Parsing
//===--------------------------------------------------------------------===//
/// Return the current token the parser is inspecting.
const Token &getToken() const { return state.curToken; }
StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
/// If the current token has the specified kind, consume it and return true.
/// If not, return false.
bool consumeIf(Token::Kind kind) {
if (state.curToken.isNot(kind))
return false;
consumeToken(kind);
return true;
}
/// Advance the current lexer onto the next token.
void consumeToken() {
assert(state.curToken.isNot(Token::eof, Token::error) &&
"shouldn't advance past EOF or errors");
state.curToken = state.lex.lexToken();
}
/// Advance the current lexer onto the next token, asserting what the expected
/// current token is. This is preferred to the above method because it leads
/// to more self-documenting code with better checking.
void consumeToken(Token::Kind kind) {
assert(state.curToken.is(kind) && "consumed an unexpected token");
consumeToken();
}
/// Consume the specified token if present and return success. On failure,
/// output a diagnostic and return failure.
ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
//===--------------------------------------------------------------------===//
// Type Parsing
//===--------------------------------------------------------------------===//
ParseResult parseFunctionResultTypes(SmallVectorImpl<Type> &elements);
ParseResult parseTypeListNoParens(SmallVectorImpl<Type> &elements);
ParseResult parseTypeListParens(SmallVectorImpl<Type> &elements);
/// Optionally parse a type.
OptionalParseResult parseOptionalType(Type &type);
/// Parse an arbitrary type.
Type parseType();
/// Parse a complex type.
Type parseComplexType();
/// Parse an extended type.
Type parseExtendedType();
/// Parse a function type.
Type parseFunctionType();
/// Parse a memref type.
Type parseMemRefType();
/// Parse a non function type.
Type parseNonFunctionType();
/// Parse a tensor type.
Type parseTensorType();
/// Parse a tuple type.
Type parseTupleType();
/// Parse a vector type.
VectorType parseVectorType();
ParseResult parseDimensionListRanked(SmallVectorImpl<int64_t> &dimensions,
bool allowDynamic = true);
ParseResult parseXInDimensionList();
/// Parse strided layout specification.
ParseResult parseStridedLayout(int64_t &offset,
SmallVectorImpl<int64_t> &strides);
// Parse a brace-delimiter list of comma-separated integers with `?` as an
// unknown marker.
ParseResult parseStrideList(SmallVectorImpl<int64_t> &dimensions);
//===--------------------------------------------------------------------===//
// Attribute Parsing
//===--------------------------------------------------------------------===//
/// Parse an arbitrary attribute with an optional type.
Attribute parseAttribute(Type type = {});
/// Parse an optional attribute with the provided type.
OptionalParseResult parseOptionalAttribute(Attribute &attribute,
Type type = {});
OptionalParseResult parseOptionalAttribute(ArrayAttr &attribute, Type type);
/// Parse an optional attribute that is demarcated by a specific token.
template <typename AttributeT>
OptionalParseResult parseOptionalAttributeWithToken(Token::Kind kind,
AttributeT &attr,
Type type = {}) {
if (getToken().isNot(kind))
return llvm::None;
if (Attribute parsedAttr = parseAttribute(type)) {
attr = parsedAttr.cast<AttributeT>();
return success();
}
return failure();
}
/// Parse an attribute dictionary.
ParseResult parseAttributeDict(NamedAttrList &attributes);
/// Parse an extended attribute.
Attribute parseExtendedAttr(Type type);
/// Parse a float attribute.
Attribute parseFloatAttr(Type type, bool isNegative);
/// Parse a decimal or a hexadecimal literal, which can be either an integer
/// or a float attribute.
Attribute parseDecOrHexAttr(Type type, bool isNegative);
/// Parse an opaque elements attribute.
Attribute parseOpaqueElementsAttr(Type attrType);
/// Parse a dense elements attribute.
Attribute parseDenseElementsAttr(Type attrType);
ShapedType parseElementsLiteralType(Type type);
/// Parse a sparse elements attribute.
Attribute parseSparseElementsAttr(Type attrType);
//===--------------------------------------------------------------------===//
// Location Parsing
//===--------------------------------------------------------------------===//
/// Parse an inline location.
ParseResult parseLocation(LocationAttr &loc);
/// Parse a raw location instance.
ParseResult parseLocationInstance(LocationAttr &loc);
/// Parse a callsite location instance.
ParseResult parseCallSiteLocation(LocationAttr &loc);
/// Parse a fused location instance.
ParseResult parseFusedLocation(LocationAttr &loc);
/// Parse a name or FileLineCol location instance.
ParseResult parseNameOrFileLineColLocation(LocationAttr &loc);
/// Parse an optional trailing location.
///
/// trailing-location ::= (`loc` `(` location `)`)?
///
ParseResult parseOptionalTrailingLocation(Location &loc) {
// If there is a 'loc' we parse a trailing location.
if (!getToken().is(Token::kw_loc))
return success();
// Parse the location.
LocationAttr directLoc;
if (parseLocation(directLoc))
return failure();
loc = directLoc;
return success();
}
//===--------------------------------------------------------------------===//
// Affine Parsing
//===--------------------------------------------------------------------===//
/// Parse a reference to either an affine map, or an integer set.
ParseResult parseAffineMapOrIntegerSetReference(AffineMap &map,
IntegerSet &set);
ParseResult parseAffineMapReference(AffineMap &map);
ParseResult parseIntegerSetReference(IntegerSet &set);
/// Parse an AffineMap where the dim and symbol identifiers are SSA ids.
ParseResult
parseAffineMapOfSSAIds(AffineMap &map,
function_ref<ParseResult(bool)> parseElement,
OpAsmParser::Delimiter delimiter);
private:
/// The Parser is subclassed and reinstantiated. Do not add additional
/// non-trivial state here, add it to the ParserState class.
ParserState &state;
};
} // end namespace detail
} // end namespace mlir
#endif // MLIR_LIB_PARSER_PARSER_H