MLIR  19.0.0git
TypeParser.cpp
Go to the documentation of this file.
1 //===- TypeParser.cpp - MLIR Type Parser Implementation -------------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the parser for the MLIR Types.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "Parser.h"
14 #include "mlir/IR/AffineMap.h"
17 #include "mlir/IR/BuiltinTypes.h"
18 #include "mlir/IR/OpDefinition.h"
19 #include "mlir/IR/TensorEncoding.h"
20 #include "mlir/IR/Types.h"
21 #include "mlir/Support/LLVM.h"
22 #include "llvm/ADT/STLExtras.h"
23 #include <cassert>
24 #include <cstdint>
25 #include <limits>
26 #include <optional>
27 
28 using namespace mlir;
29 using namespace mlir::detail;
30 
31 /// Optionally parse a type.
33  // There are many different starting tokens for a type, check them here.
34  switch (getToken().getKind()) {
35  case Token::l_paren:
36  case Token::kw_memref:
37  case Token::kw_tensor:
38  case Token::kw_complex:
39  case Token::kw_tuple:
40  case Token::kw_vector:
41  case Token::inttype:
42  case Token::kw_f8E5M2:
43  case Token::kw_f8E4M3FN:
44  case Token::kw_f8E5M2FNUZ:
45  case Token::kw_f8E4M3FNUZ:
46  case Token::kw_f8E4M3B11FNUZ:
47  case Token::kw_bf16:
48  case Token::kw_f16:
49  case Token::kw_tf32:
50  case Token::kw_f32:
51  case Token::kw_f64:
52  case Token::kw_f80:
53  case Token::kw_f128:
54  case Token::kw_index:
55  case Token::kw_none:
56  case Token::exclamation_identifier:
57  return failure(!(type = parseType()));
58 
59  default:
60  return std::nullopt;
61  }
62 }
63 
64 /// Parse an arbitrary type.
65 ///
66 /// type ::= function-type
67 /// | non-function-type
68 ///
70  if (getToken().is(Token::l_paren))
71  return parseFunctionType();
72  return parseNonFunctionType();
73 }
74 
75 /// Parse a function result type.
76 ///
77 /// function-result-type ::= type-list-parens
78 /// | non-function-type
79 ///
81  if (getToken().is(Token::l_paren))
82  return parseTypeListParens(elements);
83 
85  if (!t)
86  return failure();
87  elements.push_back(t);
88  return success();
89 }
90 
91 /// Parse a list of types without an enclosing parenthesis. The list must have
92 /// at least one member.
93 ///
94 /// type-list-no-parens ::= type (`,` type)*
95 ///
97  auto parseElt = [&]() -> ParseResult {
98  auto elt = parseType();
99  elements.push_back(elt);
100  return elt ? success() : failure();
101  };
102 
103  return parseCommaSeparatedList(parseElt);
104 }
105 
106 /// Parse a parenthesized list of types.
107 ///
108 /// type-list-parens ::= `(` `)`
109 /// | `(` type-list-no-parens `)`
110 ///
112  if (parseToken(Token::l_paren, "expected '('"))
113  return failure();
114 
115  // Handle empty lists.
116  if (getToken().is(Token::r_paren))
117  return consumeToken(), success();
118 
119  if (parseTypeListNoParens(elements) ||
120  parseToken(Token::r_paren, "expected ')'"))
121  return failure();
122  return success();
123 }
124 
125 /// Parse a complex type.
126 ///
127 /// complex-type ::= `complex` `<` type `>`
128 ///
130  consumeToken(Token::kw_complex);
131 
132  // Parse the '<'.
133  if (parseToken(Token::less, "expected '<' in complex type"))
134  return nullptr;
135 
136  SMLoc elementTypeLoc = getToken().getLoc();
137  auto elementType = parseType();
138  if (!elementType ||
139  parseToken(Token::greater, "expected '>' in complex type"))
140  return nullptr;
141  if (!isa<FloatType>(elementType) && !isa<IntegerType>(elementType))
142  return emitError(elementTypeLoc, "invalid element type for complex"),
143  nullptr;
144 
145  return ComplexType::get(elementType);
146 }
147 
148 /// Parse a function type.
149 ///
150 /// function-type ::= type-list-parens `->` function-result-type
151 ///
153  assert(getToken().is(Token::l_paren));
154 
155  SmallVector<Type, 4> arguments, results;
156  if (parseTypeListParens(arguments) ||
157  parseToken(Token::arrow, "expected '->' in function type") ||
158  parseFunctionResultTypes(results))
159  return nullptr;
160 
161  return builder.getFunctionType(arguments, results);
162 }
163 
164 /// Parse a memref type.
165 ///
166 /// memref-type ::= ranked-memref-type | unranked-memref-type
167 ///
168 /// ranked-memref-type ::= `memref` `<` dimension-list-ranked type
169 /// (`,` layout-specification)? (`,` memory-space)? `>`
170 ///
171 /// unranked-memref-type ::= `memref` `<*x` type (`,` memory-space)? `>`
172 ///
173 /// stride-list ::= `[` (dimension (`,` dimension)*)? `]`
174 /// strided-layout ::= `offset:` dimension `,` `strides: ` stride-list
175 /// layout-specification ::= semi-affine-map | strided-layout | attribute
176 /// memory-space ::= integer-literal | attribute
177 ///
179  SMLoc loc = getToken().getLoc();
180  consumeToken(Token::kw_memref);
181 
182  if (parseToken(Token::less, "expected '<' in memref type"))
183  return nullptr;
184 
185  bool isUnranked;
186  SmallVector<int64_t, 4> dimensions;
187 
188  if (consumeIf(Token::star)) {
189  // This is an unranked memref type.
190  isUnranked = true;
191  if (parseXInDimensionList())
192  return nullptr;
193 
194  } else {
195  isUnranked = false;
196  if (parseDimensionListRanked(dimensions))
197  return nullptr;
198  }
199 
200  // Parse the element type.
201  auto typeLoc = getToken().getLoc();
202  auto elementType = parseType();
203  if (!elementType)
204  return nullptr;
205 
206  // Check that memref is formed from allowed types.
207  if (!BaseMemRefType::isValidElementType(elementType))
208  return emitError(typeLoc, "invalid memref element type"), nullptr;
209 
210  MemRefLayoutAttrInterface layout;
211  Attribute memorySpace;
212 
213  auto parseElt = [&]() -> ParseResult {
214  // Either it is MemRefLayoutAttrInterface or memory space attribute.
215  Attribute attr = parseAttribute();
216  if (!attr)
217  return failure();
218 
219  if (isa<MemRefLayoutAttrInterface>(attr)) {
220  layout = cast<MemRefLayoutAttrInterface>(attr);
221  } else if (memorySpace) {
222  return emitError("multiple memory spaces specified in memref type");
223  } else {
224  memorySpace = attr;
225  return success();
226  }
227 
228  if (isUnranked)
229  return emitError("cannot have affine map for unranked memref type");
230  if (memorySpace)
231  return emitError("expected memory space to be last in memref type");
232 
233  return success();
234  };
235 
236  // Parse a list of mappings and address space if present.
237  if (!consumeIf(Token::greater)) {
238  // Parse comma separated list of affine maps, followed by memory space.
239  if (parseToken(Token::comma, "expected ',' or '>' in memref type") ||
240  parseCommaSeparatedListUntil(Token::greater, parseElt,
241  /*allowEmptyList=*/false)) {
242  return nullptr;
243  }
244  }
245 
246  if (isUnranked)
247  return getChecked<UnrankedMemRefType>(loc, elementType, memorySpace);
248 
249  return getChecked<MemRefType>(loc, dimensions, elementType, layout,
250  memorySpace);
251 }
252 
253 /// Parse any type except the function type.
254 ///
255 /// non-function-type ::= integer-type
256 /// | index-type
257 /// | float-type
258 /// | extended-type
259 /// | vector-type
260 /// | tensor-type
261 /// | memref-type
262 /// | complex-type
263 /// | tuple-type
264 /// | none-type
265 ///
266 /// index-type ::= `index`
267 /// float-type ::= `f16` | `bf16` | `f32` | `f64` | `f80` | `f128`
268 /// none-type ::= `none`
269 ///
271  switch (getToken().getKind()) {
272  default:
273  return (emitWrongTokenError("expected non-function type"), nullptr);
274  case Token::kw_memref:
275  return parseMemRefType();
276  case Token::kw_tensor:
277  return parseTensorType();
278  case Token::kw_complex:
279  return parseComplexType();
280  case Token::kw_tuple:
281  return parseTupleType();
282  case Token::kw_vector:
283  return parseVectorType();
284  // integer-type
285  case Token::inttype: {
286  auto width = getToken().getIntTypeBitwidth();
287  if (!width.has_value())
288  return (emitError("invalid integer width"), nullptr);
289  if (*width > IntegerType::kMaxWidth) {
290  emitError(getToken().getLoc(), "integer bitwidth is limited to ")
291  << IntegerType::kMaxWidth << " bits";
292  return nullptr;
293  }
294 
295  IntegerType::SignednessSemantics signSemantics = IntegerType::Signless;
296  if (std::optional<bool> signedness = getToken().getIntTypeSignedness())
297  signSemantics = *signedness ? IntegerType::Signed : IntegerType::Unsigned;
298 
299  consumeToken(Token::inttype);
300  return IntegerType::get(getContext(), *width, signSemantics);
301  }
302 
303  // float-type
304  case Token::kw_f8E5M2:
305  consumeToken(Token::kw_f8E5M2);
306  return builder.getFloat8E5M2Type();
307  case Token::kw_f8E4M3FN:
308  consumeToken(Token::kw_f8E4M3FN);
309  return builder.getFloat8E4M3FNType();
310  case Token::kw_f8E5M2FNUZ:
311  consumeToken(Token::kw_f8E5M2FNUZ);
313  case Token::kw_f8E4M3FNUZ:
314  consumeToken(Token::kw_f8E4M3FNUZ);
316  case Token::kw_f8E4M3B11FNUZ:
317  consumeToken(Token::kw_f8E4M3B11FNUZ);
319  case Token::kw_bf16:
320  consumeToken(Token::kw_bf16);
321  return builder.getBF16Type();
322  case Token::kw_f16:
323  consumeToken(Token::kw_f16);
324  return builder.getF16Type();
325  case Token::kw_tf32:
326  consumeToken(Token::kw_tf32);
327  return builder.getTF32Type();
328  case Token::kw_f32:
329  consumeToken(Token::kw_f32);
330  return builder.getF32Type();
331  case Token::kw_f64:
332  consumeToken(Token::kw_f64);
333  return builder.getF64Type();
334  case Token::kw_f80:
335  consumeToken(Token::kw_f80);
336  return builder.getF80Type();
337  case Token::kw_f128:
338  consumeToken(Token::kw_f128);
339  return builder.getF128Type();
340 
341  // index-type
342  case Token::kw_index:
343  consumeToken(Token::kw_index);
344  return builder.getIndexType();
345 
346  // none-type
347  case Token::kw_none:
348  consumeToken(Token::kw_none);
349  return builder.getNoneType();
350 
351  // extended type
352  case Token::exclamation_identifier:
353  return parseExtendedType();
354 
355  // Handle completion of a dialect type.
356  case Token::code_complete:
357  if (getToken().isCodeCompletionFor(Token::exclamation_identifier))
358  return parseExtendedType();
359  return codeCompleteType();
360  }
361 }
362 
363 /// Parse a tensor type.
364 ///
365 /// tensor-type ::= `tensor` `<` dimension-list type `>`
366 /// dimension-list ::= dimension-list-ranked | `*x`
367 ///
369  consumeToken(Token::kw_tensor);
370 
371  if (parseToken(Token::less, "expected '<' in tensor type"))
372  return nullptr;
373 
374  bool isUnranked;
375  SmallVector<int64_t, 4> dimensions;
376 
377  if (consumeIf(Token::star)) {
378  // This is an unranked tensor type.
379  isUnranked = true;
380 
381  if (parseXInDimensionList())
382  return nullptr;
383 
384  } else {
385  isUnranked = false;
386  if (parseDimensionListRanked(dimensions))
387  return nullptr;
388  }
389 
390  // Parse the element type.
391  auto elementTypeLoc = getToken().getLoc();
392  auto elementType = parseType();
393 
394  // Parse an optional encoding attribute.
395  Attribute encoding;
396  if (consumeIf(Token::comma)) {
397  auto parseResult = parseOptionalAttribute(encoding);
398  if (parseResult.has_value()) {
399  if (failed(parseResult.value()))
400  return nullptr;
401  if (auto v = dyn_cast_or_null<VerifiableTensorEncoding>(encoding)) {
402  if (failed(v.verifyEncoding(dimensions, elementType,
403  [&] { return emitError(); })))
404  return nullptr;
405  }
406  }
407  }
408 
409  if (!elementType || parseToken(Token::greater, "expected '>' in tensor type"))
410  return nullptr;
411  if (!TensorType::isValidElementType(elementType))
412  return emitError(elementTypeLoc, "invalid tensor element type"), nullptr;
413 
414  if (isUnranked) {
415  if (encoding)
416  return emitError("cannot apply encoding to unranked tensor"), nullptr;
417  return UnrankedTensorType::get(elementType);
418  }
419  return RankedTensorType::get(dimensions, elementType, encoding);
420 }
421 
422 /// Parse a tuple type.
423 ///
424 /// tuple-type ::= `tuple` `<` (type (`,` type)*)? `>`
425 ///
427  consumeToken(Token::kw_tuple);
428 
429  // Parse the '<'.
430  if (parseToken(Token::less, "expected '<' in tuple type"))
431  return nullptr;
432 
433  // Check for an empty tuple by directly parsing '>'.
434  if (consumeIf(Token::greater))
435  return TupleType::get(getContext());
436 
437  // Parse the element types and the '>'.
438  SmallVector<Type, 4> types;
439  if (parseTypeListNoParens(types) ||
440  parseToken(Token::greater, "expected '>' in tuple type"))
441  return nullptr;
442 
443  return TupleType::get(getContext(), types);
444 }
445 
446 /// Parse a vector type.
447 ///
448 /// vector-type ::= `vector` `<` vector-dim-list vector-element-type `>`
449 /// vector-dim-list := (static-dim-list `x`)? (`[` static-dim-list `]` `x`)?
450 /// static-dim-list ::= decimal-literal (`x` decimal-literal)*
451 ///
453  consumeToken(Token::kw_vector);
454 
455  if (parseToken(Token::less, "expected '<' in vector type"))
456  return nullptr;
457 
458  SmallVector<int64_t, 4> dimensions;
459  SmallVector<bool, 4> scalableDims;
460  if (parseVectorDimensionList(dimensions, scalableDims))
461  return nullptr;
462  if (any_of(dimensions, [](int64_t i) { return i <= 0; }))
463  return emitError(getToken().getLoc(),
464  "vector types must have positive constant sizes"),
465  nullptr;
466 
467  // Parse the element type.
468  auto typeLoc = getToken().getLoc();
469  auto elementType = parseType();
470  if (!elementType || parseToken(Token::greater, "expected '>' in vector type"))
471  return nullptr;
472 
473  if (!VectorType::isValidElementType(elementType))
474  return emitError(typeLoc, "vector elements must be int/index/float type"),
475  nullptr;
476 
477  return VectorType::get(dimensions, elementType, scalableDims);
478 }
479 
480 /// Parse a dimension list in a vector type. This populates the dimension list.
481 /// For i-th dimension, `scalableDims[i]` contains either:
482 /// * `false` for a non-scalable dimension (e.g. `4`),
483 /// * `true` for a scalable dimension (e.g. `[4]`).
484 ///
485 /// vector-dim-list := (static-dim-list `x`)?
486 /// static-dim-list ::= static-dim (`x` static-dim)*
487 /// static-dim ::= (decimal-literal | `[` decimal-literal `]`)
488 ///
489 ParseResult
491  SmallVectorImpl<bool> &scalableDims) {
492  // If there is a set of fixed-length dimensions, consume it
493  while (getToken().is(Token::integer) || getToken().is(Token::l_square)) {
494  int64_t value;
495  bool scalable = consumeIf(Token::l_square);
496  if (parseIntegerInDimensionList(value))
497  return failure();
498  dimensions.push_back(value);
499  if (scalable) {
500  if (!consumeIf(Token::r_square))
501  return emitWrongTokenError("missing ']' closing scalable dimension");
502  }
503  scalableDims.push_back(scalable);
504  // Make sure we have an 'x' or something like 'xbf32'.
505  if (parseXInDimensionList())
506  return failure();
507  }
508 
509  return success();
510 }
511 
512 /// Parse a dimension list of a tensor or memref type. This populates the
513 /// dimension list, using ShapedType::kDynamic for the `?` dimensions if
514 /// `allowDynamic` is set and errors out on `?` otherwise. Parsing the trailing
515 /// `x` is configurable.
516 ///
517 /// dimension-list ::= eps | dimension (`x` dimension)*
518 /// dimension-list-with-trailing-x ::= (dimension `x`)*
519 /// dimension ::= `?` | decimal-literal
520 ///
521 /// When `allowDynamic` is not set, this is used to parse:
522 ///
523 /// static-dimension-list ::= eps | decimal-literal (`x` decimal-literal)*
524 /// static-dimension-list-with-trailing-x ::= (dimension `x`)*
525 ParseResult
527  bool allowDynamic, bool withTrailingX) {
528  auto parseDim = [&]() -> LogicalResult {
529  auto loc = getToken().getLoc();
530  if (consumeIf(Token::question)) {
531  if (!allowDynamic)
532  return emitError(loc, "expected static shape");
533  dimensions.push_back(ShapedType::kDynamic);
534  } else {
535  int64_t value;
536  if (failed(parseIntegerInDimensionList(value)))
537  return failure();
538  dimensions.push_back(value);
539  }
540  return success();
541  };
542 
543  if (withTrailingX) {
544  while (getToken().isAny(Token::integer, Token::question)) {
545  if (failed(parseDim()) || failed(parseXInDimensionList()))
546  return failure();
547  }
548  return success();
549  }
550 
551  if (getToken().isAny(Token::integer, Token::question)) {
552  if (failed(parseDim()))
553  return failure();
554  while (getToken().is(Token::bare_identifier) &&
555  getTokenSpelling()[0] == 'x') {
556  if (failed(parseXInDimensionList()) || failed(parseDim()))
557  return failure();
558  }
559  }
560  return success();
561 }
562 
563 ParseResult Parser::parseIntegerInDimensionList(int64_t &value) {
564  // Hexadecimal integer literals (starting with `0x`) are not allowed in
565  // aggregate type declarations. Therefore, `0xf32` should be processed as
566  // a sequence of separate elements `0`, `x`, `f32`.
567  if (getTokenSpelling().size() > 1 && getTokenSpelling()[1] == 'x') {
568  // We can get here only if the token is an integer literal. Hexadecimal
569  // integer literals can only start with `0x` (`1x` wouldn't lex as a
570  // literal, just `1` would, at which point we don't get into this
571  // branch).
572  assert(getTokenSpelling()[0] == '0' && "invalid integer literal");
573  value = 0;
574  state.lex.resetPointer(getTokenSpelling().data() + 1);
575  consumeToken();
576  } else {
577  // Make sure this integer value is in bound and valid.
578  std::optional<uint64_t> dimension = getToken().getUInt64IntegerValue();
579  if (!dimension ||
580  *dimension > (uint64_t)std::numeric_limits<int64_t>::max())
581  return emitError("invalid dimension");
582  value = (int64_t)*dimension;
583  consumeToken(Token::integer);
584  }
585  return success();
586 }
587 
588 /// Parse an 'x' token in a dimension list, handling the case where the x is
589 /// juxtaposed with an element type, as in "xf32", leaving the "f32" as the next
590 /// token.
592  if (getToken().isNot(Token::bare_identifier) || getTokenSpelling()[0] != 'x')
593  return emitWrongTokenError("expected 'x' in dimension list");
594 
595  // If we had a prefix of 'x', lex the next token immediately after the 'x'.
596  if (getTokenSpelling().size() != 1)
597  state.lex.resetPointer(getTokenSpelling().data() + 1);
598 
599  // Consume the 'x'.
600  consumeToken(Token::bare_identifier);
601 
602  return success();
603 }
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
Attributes are known-constant values of operations.
Definition: Attributes.h:25
static bool isValidElementType(Type type)
Return true if the specified element type is ok in a memref.
Definition: BuiltinTypes.h:400
FloatType getFloat8E5M2Type()
Definition: Builders.cpp:37
FloatType getF80Type()
Definition: Builders.cpp:67
FloatType getF128Type()
Definition: Builders.cpp:69
FloatType getF32Type()
Definition: Builders.cpp:63
FloatType getTF32Type()
Definition: Builders.cpp:61
FloatType getFloat8E4M3B11FNUZType()
Definition: Builders.cpp:53
FunctionType getFunctionType(TypeRange inputs, TypeRange results)
Definition: Builders.cpp:96
NoneType getNoneType()
Definition: Builders.cpp:104
FloatType getF16Type()
Definition: Builders.cpp:59
FloatType getBF16Type()
Definition: Builders.cpp:57
FloatType getFloat8E4M3FNType()
Definition: Builders.cpp:41
FloatType getFloat8E4M3FNUZType()
Definition: Builders.cpp:49
IndexType getIndexType()
Definition: Builders.cpp:71
FloatType getFloat8E5M2FNUZType()
Definition: Builders.cpp:45
FloatType getF64Type()
Definition: Builders.cpp:65
void resetPointer(const char *newPointer)
Change the position of the lexer cursor.
Definition: Lexer.h:38
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:39
static bool isValidElementType(Type type)
Return true if the specified element type is ok in a tensor.
SMLoc getLoc() const
Definition: Token.cpp:24
static std::optional< uint64_t > getUInt64IntegerValue(StringRef spelling)
For an integer token, return its value as an uint64_t.
Definition: Token.cpp:45
std::optional< unsigned > getIntTypeBitwidth() const
For an inttype token, return its bitwidth.
Definition: Token.cpp:64
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
ParseResult parseXInDimensionList()
Parse an 'x' token in a dimension list, handling the case where the x is juxtaposed with an element t...
Definition: TypeParser.cpp:591
OptionalParseResult parseOptionalType(Type &type)
Optionally parse a type.
Definition: TypeParser.cpp:32
ParseResult parseToken(Token::Kind expectedToken, const Twine &message)
Consume the specified token if present and return success.
Definition: Parser.cpp:266
ParseResult parseCommaSeparatedListUntil(Token::Kind rightToken, function_ref< ParseResult()> parseElement, bool allowEmptyList=true)
Parse a comma-separated list of elements up until the specified end token.
Definition: Parser.cpp:172
Builder builder
Definition: Parser.h:30
Type parseType()
Parse an arbitrary type.
Definition: TypeParser.cpp:69
ParseResult parseTypeListParens(SmallVectorImpl< Type > &elements)
Parse a parenthesized list of types.
Definition: TypeParser.cpp:111
ParseResult parseVectorDimensionList(SmallVectorImpl< int64_t > &dimensions, SmallVectorImpl< bool > &scalableDims)
Parse a dimension list in a vector type.
Definition: TypeParser.cpp:490
Type parseMemRefType()
Parse a memref type.
Definition: TypeParser.cpp:178
Type parseNonFunctionType()
Parse a non function type.
Definition: TypeParser.cpp:270
Type codeCompleteType()
Definition: Parser.cpp:462
Type parseExtendedType()
Parse an extended type.
Type parseTupleType()
Parse a tuple type.
Definition: TypeParser.cpp:426
InFlightDiagnostic emitError(const Twine &message={})
Emit an error and return failure.
Definition: Parser.cpp:191
ParserState & state
The Parser is subclassed and reinstantiated.
Definition: Parser.h:352
Attribute parseAttribute(Type type={})
Parse an arbitrary attribute with an optional type.
StringRef getTokenSpelling() const
Definition: Parser.h:103
void consumeToken()
Advance the current lexer onto the next token.
Definition: Parser.h:118
ParseResult parseIntegerInDimensionList(int64_t &value)
Definition: TypeParser.cpp:563
Type parseComplexType()
Parse a complex type.
Definition: TypeParser.cpp:129
ParseResult parseDimensionListRanked(SmallVectorImpl< int64_t > &dimensions, bool allowDynamic=true, bool withTrailingX=true)
Parse a dimension list of a tensor or memref type.
Definition: TypeParser.cpp:526
ParseResult parseFunctionResultTypes(SmallVectorImpl< Type > &elements)
Parse a function result type.
Definition: TypeParser.cpp:80
MLIRContext * getContext() const
Definition: Parser.h:37
InFlightDiagnostic emitWrongTokenError(const Twine &message={})
Emit an error about a "wrong token".
Definition: Parser.cpp:214
ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())
Parse a list of comma-separated items with an optional delimiter.
Definition: Parser.cpp:83
VectorType parseVectorType()
Parse a vector type.
Definition: TypeParser.cpp:452
Type parseFunctionType()
Parse a function type.
Definition: TypeParser.cpp:152
OptionalParseResult parseOptionalAttribute(Attribute &attribute, Type type={})
Parse an optional attribute with the provided type.
ParseResult parseTypeListNoParens(SmallVectorImpl< Type > &elements)
Parse a list of types without an enclosing parenthesis.
Definition: TypeParser.cpp:96
const Token & getToken() const
Return the current token the parser is inspecting.
Definition: Parser.h:102
Type parseTensorType()
Parse a tensor type.
Definition: TypeParser.cpp:368
bool consumeIf(Token::Kind kind)
If the current token has the specified kind, consume it and return true.
Definition: Parser.h:110
AttrTypeReplacer.
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
Lexer lex
The lexer for the source file we're parsing.
Definition: ParserState.h:66