1 //===- Parser.h - MLIR Base Parser Class ------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef MLIR_LIB_ASMPARSER_PARSER_H
10 #define MLIR_LIB_ASMPARSER_PARSER_H
12 #include "ParserState.h"
13 #include "mlir/IR/Builders.h"
14 #include "mlir/IR/OpImplementation.h"
20 //===----------------------------------------------------------------------===//
22 //===----------------------------------------------------------------------===//
24 /// This class implement support for parsing global entities like attributes and
25 /// types. It is intended to be subclassed by specialized subparsers that
29 using Delimiter
= OpAsmParser::Delimiter
;
33 Parser(ParserState
&state
)
34 : builder(state
.config
.getContext()), state(state
) {}
36 // Helper methods to get stuff from the parser-global state.
37 ParserState
&getState() const { return state
; }
38 MLIRContext
*getContext() const { return state
.config
.getContext(); }
39 const llvm::SourceMgr
&getSourceMgr() { return state
.lex
.getSourceMgr(); }
41 /// Parse a comma-separated list of elements up until the specified end token.
43 parseCommaSeparatedListUntil(Token::Kind rightToken
,
44 function_ref
<ParseResult()> parseElement
,
45 bool allowEmptyList
= true);
47 /// Parse a list of comma-separated items with an optional delimiter. If a
48 /// delimiter is provided, then an empty list is allowed. If not, then at
49 /// least one element will be parsed.
51 parseCommaSeparatedList(Delimiter delimiter
,
52 function_ref
<ParseResult()> parseElementFn
,
53 StringRef contextMessage
= StringRef());
55 /// Parse a comma separated list of elements that must have at least one entry
58 parseCommaSeparatedList(function_ref
<ParseResult()> parseElementFn
) {
59 return parseCommaSeparatedList(Delimiter::None
, parseElementFn
);
62 /// Parse the body of a dialect symbol, which starts and ends with <>'s, and
63 /// may be recursive. Return with the 'body' StringRef encompassing the entire
64 /// body. `isCodeCompletion` is set to true if the body contained a code
65 /// completion location, in which case the body is only populated up to the
67 ParseResult
parseDialectSymbolBody(StringRef
&body
, bool &isCodeCompletion
);
68 ParseResult
parseDialectSymbolBody(StringRef
&body
) {
69 bool isCodeCompletion
= false;
70 return parseDialectSymbolBody(body
, isCodeCompletion
);
73 // We have two forms of parsing methods - those that return a non-null
74 // pointer on success, and those that return a ParseResult to indicate whether
75 // they returned a failure. The second class fills in by-reference arguments
76 // as the results of their action.
78 //===--------------------------------------------------------------------===//
80 //===--------------------------------------------------------------------===//
82 /// Emit an error and return failure.
83 InFlightDiagnostic
emitError(const Twine
&message
= {});
84 InFlightDiagnostic
emitError(SMLoc loc
, const Twine
&message
= {});
86 /// Emit an error about a "wrong token". If the current token is at the
87 /// start of a source line, this will apply heuristics to back up and report
88 /// the error at the end of the previous line, which is where the expected
89 /// token is supposed to be.
90 InFlightDiagnostic
emitWrongTokenError(const Twine
&message
= {});
92 /// Encode the specified source location information into an attribute for
93 /// attachment to the IR.
94 Location
getEncodedSourceLocation(SMLoc loc
) {
95 return state
.lex
.getEncodedSourceLocation(loc
);
98 //===--------------------------------------------------------------------===//
100 //===--------------------------------------------------------------------===//
102 /// Return the current token the parser is inspecting.
103 const Token
&getToken() const { return state
.curToken
; }
104 StringRef
getTokenSpelling() const { return state
.curToken
.getSpelling(); }
106 /// Return the last parsed token.
107 const Token
&getLastToken() const { return state
.lastToken
; }
109 /// If the current token has the specified kind, consume it and return true.
110 /// If not, return false.
111 bool consumeIf(Token::Kind kind
) {
112 if (state
.curToken
.isNot(kind
))
118 /// Advance the current lexer onto the next token.
119 void consumeToken() {
120 assert(state
.curToken
.isNot(Token::eof
, Token::error
) &&
121 "shouldn't advance past EOF or errors");
122 state
.lastToken
= state
.curToken
;
123 state
.curToken
= state
.lex
.lexToken();
126 /// Advance the current lexer onto the next token, asserting what the expected
127 /// current token is. This is preferred to the above method because it leads
128 /// to more self-documenting code with better checking.
129 void consumeToken(Token::Kind kind
) {
130 assert(state
.curToken
.is(kind
) && "consumed an unexpected token");
134 /// Reset the parser to the given lexer position. Resetting the parser/lexer
135 /// position does not update 'state.lastToken'. 'state.lastToken' is the
136 /// last parsed token, and is used to provide the scope end location for
137 /// OperationDefinitions. To ensure the correctness of the end location, the
138 /// last consumed token of an OperationDefinition needs to be the last token
140 void resetToken(const char *tokPos
) {
141 state
.lex
.resetPointer(tokPos
);
142 state
.curToken
= state
.lex
.lexToken();
145 /// Consume the specified token if present and return success. On failure,
146 /// output a diagnostic and return failure.
147 ParseResult
parseToken(Token::Kind expectedToken
, const Twine
&message
);
149 /// Parse an optional integer value from the stream.
150 OptionalParseResult
parseOptionalInteger(APInt
&result
);
152 /// Parse an optional integer value only in decimal format from the stream.
153 OptionalParseResult
parseOptionalDecimalInteger(APInt
&result
);
155 /// Parse a floating point value from a literal.
156 ParseResult
parseFloatFromLiteral(std::optional
<APFloat
> &result
,
157 const Token
&tok
, bool isNegative
,
158 const llvm::fltSemantics
&semantics
);
160 /// Parse a floating point value from an integer literal token.
161 ParseResult
parseFloatFromIntegerLiteral(std::optional
<APFloat
> &result
,
162 const Token
&tok
, bool isNegative
,
163 const llvm::fltSemantics
&semantics
);
165 /// Returns true if the current token corresponds to a keyword.
166 bool isCurrentTokenAKeyword() const {
167 return getToken().isAny(Token::bare_identifier
, Token::inttype
) ||
168 getToken().isKeyword();
171 /// Parse a keyword, if present, into 'keyword'.
172 ParseResult
parseOptionalKeyword(StringRef
*keyword
);
174 //===--------------------------------------------------------------------===//
176 //===--------------------------------------------------------------------===//
178 /// Parse a handle to a dialect resource within the assembly format.
179 FailureOr
<AsmDialectResourceHandle
>
180 parseResourceHandle(const OpAsmDialectInterface
*dialect
, StringRef
&name
);
181 FailureOr
<AsmDialectResourceHandle
> parseResourceHandle(Dialect
*dialect
);
183 //===--------------------------------------------------------------------===//
185 //===--------------------------------------------------------------------===//
187 /// Invoke the `getChecked` method of the given Attribute or Type class, using
188 /// the provided location to emit errors in the case of failure. Note that
189 /// unlike `OpBuilder::getType`, this method does not implicitly insert a
190 /// context parameter.
191 template <typename T
, typename
... ParamsT
>
192 T
getChecked(SMLoc loc
, ParamsT
&&...params
) {
193 return T::getChecked([&] { return emitError(loc
); },
194 std::forward
<ParamsT
>(params
)...);
197 ParseResult
parseFunctionResultTypes(SmallVectorImpl
<Type
> &elements
);
198 ParseResult
parseTypeListNoParens(SmallVectorImpl
<Type
> &elements
);
199 ParseResult
parseTypeListParens(SmallVectorImpl
<Type
> &elements
);
201 /// Optionally parse a type.
202 OptionalParseResult
parseOptionalType(Type
&type
);
204 /// Parse an arbitrary type.
207 /// Parse a complex type.
208 Type
parseComplexType();
210 /// Parse an extended type.
211 Type
parseExtendedType();
213 /// Parse a function type.
214 Type
parseFunctionType();
216 /// Parse a memref type.
217 Type
parseMemRefType();
219 /// Parse a non function type.
220 Type
parseNonFunctionType();
222 /// Parse a tensor type.
223 Type
parseTensorType();
225 /// Parse a tuple type.
226 Type
parseTupleType();
228 /// Parse a vector type.
229 VectorType
parseVectorType();
230 ParseResult
parseVectorDimensionList(SmallVectorImpl
<int64_t> &dimensions
,
231 SmallVectorImpl
<bool> &scalableDims
);
232 ParseResult
parseDimensionListRanked(SmallVectorImpl
<int64_t> &dimensions
,
233 bool allowDynamic
= true,
234 bool withTrailingX
= true);
235 ParseResult
parseIntegerInDimensionList(int64_t &value
);
236 ParseResult
parseXInDimensionList();
238 //===--------------------------------------------------------------------===//
240 //===--------------------------------------------------------------------===//
242 /// Parse an arbitrary attribute with an optional type.
243 Attribute
parseAttribute(Type type
= {});
245 /// Parse an optional attribute with the provided type.
246 OptionalParseResult
parseOptionalAttribute(Attribute
&attribute
,
248 OptionalParseResult
parseOptionalAttribute(ArrayAttr
&attribute
, Type type
);
249 OptionalParseResult
parseOptionalAttribute(StringAttr
&attribute
, Type type
);
250 OptionalParseResult
parseOptionalAttribute(SymbolRefAttr
&result
, Type type
);
252 /// Parse an optional attribute that is demarcated by a specific token.
253 template <typename AttributeT
>
254 OptionalParseResult
parseOptionalAttributeWithToken(Token::Kind kind
,
257 if (getToken().isNot(kind
))
260 if (Attribute parsedAttr
= parseAttribute(type
)) {
261 attr
= cast
<AttributeT
>(parsedAttr
);
267 /// Parse an attribute dictionary.
268 ParseResult
parseAttributeDict(NamedAttrList
&attributes
);
270 /// Parse a distinct attribute.
271 Attribute
parseDistinctAttr(Type type
);
273 /// Parse an extended attribute.
274 Attribute
parseExtendedAttr(Type type
);
276 /// Parse a float attribute.
277 Attribute
parseFloatAttr(Type type
, bool isNegative
);
279 /// Parse a decimal or a hexadecimal literal, which can be either an integer
280 /// or a float attribute.
281 Attribute
parseDecOrHexAttr(Type type
, bool isNegative
);
283 /// Parse a dense elements attribute.
284 Attribute
parseDenseElementsAttr(Type attrType
);
285 ShapedType
parseElementsLiteralType(Type type
);
287 /// Parse a dense resource elements attribute.
288 Attribute
parseDenseResourceElementsAttr(Type attrType
);
290 /// Parse a DenseArrayAttr.
291 Attribute
parseDenseArrayAttr(Type type
);
293 /// Parse a sparse elements attribute.
294 Attribute
parseSparseElementsAttr(Type attrType
);
296 /// Parse a strided layout attribute.
297 Attribute
parseStridedLayoutAttr();
299 //===--------------------------------------------------------------------===//
301 //===--------------------------------------------------------------------===//
303 /// Parse a raw location instance.
304 ParseResult
parseLocationInstance(LocationAttr
&loc
);
306 /// Parse a callsite location instance.
307 ParseResult
parseCallSiteLocation(LocationAttr
&loc
);
309 /// Parse a fused location instance.
310 ParseResult
parseFusedLocation(LocationAttr
&loc
);
312 /// Parse a name or FileLineCol location instance.
313 ParseResult
parseNameOrFileLineColLocation(LocationAttr
&loc
);
315 //===--------------------------------------------------------------------===//
317 //===--------------------------------------------------------------------===//
319 /// Parse a reference to either an affine map, expr, or an integer set.
320 ParseResult
parseAffineMapOrIntegerSetReference(AffineMap
&map
,
322 ParseResult
parseAffineMapReference(AffineMap
&map
);
324 parseAffineExprReference(ArrayRef
<std::pair
<StringRef
, AffineExpr
>> symbolSet
,
326 ParseResult
parseIntegerSetReference(IntegerSet
&set
);
328 /// Parse an AffineMap where the dim and symbol identifiers are SSA ids.
330 parseAffineMapOfSSAIds(AffineMap
&map
,
331 function_ref
<ParseResult(bool)> parseElement
,
332 Delimiter delimiter
);
334 /// Parse an AffineExpr where dim and symbol identifiers are SSA ids.
336 parseAffineExprOfSSAIds(AffineExpr
&expr
,
337 function_ref
<ParseResult(bool)> parseElement
);
339 //===--------------------------------------------------------------------===//
341 //===--------------------------------------------------------------------===//
343 /// The set of various code completion methods. Every completion method
344 /// returns `failure` to signal that parsing should abort after any desired
345 /// completions have been enqueued. Note that `failure` is does not mean
346 /// completion failed, it's just a signal to the parser to stop.
348 ParseResult
codeCompleteDialectName();
349 ParseResult
codeCompleteOperationName(StringRef dialectName
);
350 ParseResult
codeCompleteDialectOrElidedOpName(SMLoc loc
);
351 ParseResult
codeCompleteStringDialectOrOperationName(StringRef name
);
352 ParseResult
codeCompleteExpectedTokens(ArrayRef
<StringRef
> tokens
);
353 ParseResult
codeCompleteOptionalTokens(ArrayRef
<StringRef
> tokens
);
355 Attribute
codeCompleteAttribute();
356 Type
codeCompleteType();
358 codeCompleteDialectSymbol(const llvm::StringMap
<Attribute
> &aliases
);
359 Type
codeCompleteDialectSymbol(const llvm::StringMap
<Type
> &aliases
);
362 /// The Parser is subclassed and reinstantiated. Do not add additional
363 /// non-trivial state here, add it to the ParserState class.
366 } // namespace detail
369 #endif // MLIR_LIB_ASMPARSER_PARSER_H