1 | //===- AsmParserImpl.h - MLIR AsmParserImpl Class ---------------*- 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-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef MLIR_LIB_ASMPARSER_ASMPARSERIMPL_H |
10 | #define MLIR_LIB_ASMPARSER_ASMPARSERIMPL_H |
11 | |
12 | #include "Parser.h" |
13 | #include "mlir/AsmParser/AsmParserState.h" |
14 | #include "mlir/IR/Builders.h" |
15 | #include "mlir/IR/OpImplementation.h" |
16 | #include "llvm/Support/Base64.h" |
17 | #include <optional> |
18 | |
19 | namespace mlir { |
20 | namespace detail { |
21 | //===----------------------------------------------------------------------===// |
22 | // AsmParserImpl |
23 | //===----------------------------------------------------------------------===// |
24 | |
25 | /// This class provides the implementation of the generic parser methods within |
26 | /// AsmParser. |
27 | template <typename BaseT> |
28 | class AsmParserImpl : public BaseT { |
29 | public: |
30 | AsmParserImpl(SMLoc nameLoc, Parser &parser) |
31 | : nameLoc(nameLoc), parser(parser) {} |
32 | ~AsmParserImpl() override = default; |
33 | |
34 | /// Return the location of the original name token. |
35 | SMLoc getNameLoc() const override { return nameLoc; } |
36 | |
37 | //===--------------------------------------------------------------------===// |
38 | // Utilities |
39 | //===--------------------------------------------------------------------===// |
40 | |
41 | /// Return if any errors were emitted during parsing. |
42 | bool didEmitError() const { return emittedError; } |
43 | |
44 | /// Emit a diagnostic at the specified location and return failure. |
45 | InFlightDiagnostic emitError(SMLoc loc, const Twine &message) override { |
46 | emittedError = true; |
47 | return parser.emitError(loc, message); |
48 | } |
49 | |
50 | /// Return a builder which provides useful access to MLIRContext, global |
51 | /// objects like types and attributes. |
52 | Builder &getBuilder() const override { return parser.builder; } |
53 | |
54 | /// Get the location of the next token and store it into the argument. This |
55 | /// always succeeds. |
56 | SMLoc getCurrentLocation() override { return parser.getToken().getLoc(); } |
57 | |
58 | /// Re-encode the given source location as an MLIR location and return it. |
59 | Location getEncodedSourceLoc(SMLoc loc) override { |
60 | return parser.getEncodedSourceLocation(loc); |
61 | } |
62 | |
63 | //===--------------------------------------------------------------------===// |
64 | // Token Parsing |
65 | //===--------------------------------------------------------------------===// |
66 | |
67 | using Delimiter = AsmParser::Delimiter; |
68 | |
69 | /// Parse a `->` token. |
70 | ParseResult parseArrow() override { |
71 | return parser.parseToken(expectedToken: Token::arrow, message: "expected '->'"); |
72 | } |
73 | |
74 | /// Parses a `->` if present. |
75 | ParseResult parseOptionalArrow() override { |
76 | return success(IsSuccess: parser.consumeIf(kind: Token::arrow)); |
77 | } |
78 | |
79 | /// Parse a '{' token. |
80 | ParseResult parseLBrace() override { |
81 | return parser.parseToken(expectedToken: Token::l_brace, message: "expected '{'"); |
82 | } |
83 | |
84 | /// Parse a '{' token if present |
85 | ParseResult parseOptionalLBrace() override { |
86 | return success(IsSuccess: parser.consumeIf(kind: Token::l_brace)); |
87 | } |
88 | |
89 | /// Parse a `}` token. |
90 | ParseResult parseRBrace() override { |
91 | return parser.parseToken(expectedToken: Token::r_brace, message: "expected '}'"); |
92 | } |
93 | |
94 | /// Parse a `}` token if present |
95 | ParseResult parseOptionalRBrace() override { |
96 | return success(IsSuccess: parser.consumeIf(kind: Token::r_brace)); |
97 | } |
98 | |
99 | /// Parse a `:` token. |
100 | ParseResult parseColon() override { |
101 | return parser.parseToken(expectedToken: Token::colon, message: "expected ':'"); |
102 | } |
103 | |
104 | /// Parse a `:` token if present. |
105 | ParseResult parseOptionalColon() override { |
106 | return success(IsSuccess: parser.consumeIf(kind: Token::colon)); |
107 | } |
108 | |
109 | /// Parse a `,` token. |
110 | ParseResult parseComma() override { |
111 | return parser.parseToken(expectedToken: Token::comma, message: "expected ','"); |
112 | } |
113 | |
114 | /// Parse a `,` token if present. |
115 | ParseResult parseOptionalComma() override { |
116 | return success(IsSuccess: parser.consumeIf(kind: Token::comma)); |
117 | } |
118 | |
119 | /// Parses a `...`. |
120 | ParseResult parseEllipsis() override { |
121 | return parser.parseToken(expectedToken: Token::ellipsis, message: "expected '...'"); |
122 | } |
123 | |
124 | /// Parses a `...` if present. |
125 | ParseResult parseOptionalEllipsis() override { |
126 | return success(IsSuccess: parser.consumeIf(kind: Token::ellipsis)); |
127 | } |
128 | |
129 | /// Parse a `=` token. |
130 | ParseResult parseEqual() override { |
131 | return parser.parseToken(expectedToken: Token::equal, message: "expected '='"); |
132 | } |
133 | |
134 | /// Parse a `=` token if present. |
135 | ParseResult parseOptionalEqual() override { |
136 | return success(IsSuccess: parser.consumeIf(kind: Token::equal)); |
137 | } |
138 | |
139 | /// Parse a '<' token. |
140 | ParseResult parseLess() override { |
141 | return parser.parseToken(expectedToken: Token::less, message: "expected '<'"); |
142 | } |
143 | |
144 | /// Parse a `<` token if present. |
145 | ParseResult parseOptionalLess() override { |
146 | return success(IsSuccess: parser.consumeIf(kind: Token::less)); |
147 | } |
148 | |
149 | /// Parse a '>' token. |
150 | ParseResult parseGreater() override { |
151 | return parser.parseToken(expectedToken: Token::greater, message: "expected '>'"); |
152 | } |
153 | |
154 | /// Parse a `>` token if present. |
155 | ParseResult parseOptionalGreater() override { |
156 | return success(IsSuccess: parser.consumeIf(kind: Token::greater)); |
157 | } |
158 | |
159 | /// Parse a `(` token. |
160 | ParseResult parseLParen() override { |
161 | return parser.parseToken(expectedToken: Token::l_paren, message: "expected '('"); |
162 | } |
163 | |
164 | /// Parses a '(' if present. |
165 | ParseResult parseOptionalLParen() override { |
166 | return success(IsSuccess: parser.consumeIf(kind: Token::l_paren)); |
167 | } |
168 | |
169 | /// Parse a `)` token. |
170 | ParseResult parseRParen() override { |
171 | return parser.parseToken(expectedToken: Token::r_paren, message: "expected ')'"); |
172 | } |
173 | |
174 | /// Parses a ')' if present. |
175 | ParseResult parseOptionalRParen() override { |
176 | return success(IsSuccess: parser.consumeIf(kind: Token::r_paren)); |
177 | } |
178 | |
179 | /// Parse a `[` token. |
180 | ParseResult parseLSquare() override { |
181 | return parser.parseToken(expectedToken: Token::l_square, message: "expected '['"); |
182 | } |
183 | |
184 | /// Parses a '[' if present. |
185 | ParseResult parseOptionalLSquare() override { |
186 | return success(IsSuccess: parser.consumeIf(kind: Token::l_square)); |
187 | } |
188 | |
189 | /// Parse a `]` token. |
190 | ParseResult parseRSquare() override { |
191 | return parser.parseToken(expectedToken: Token::r_square, message: "expected ']'"); |
192 | } |
193 | |
194 | /// Parses a ']' if present. |
195 | ParseResult parseOptionalRSquare() override { |
196 | return success(IsSuccess: parser.consumeIf(kind: Token::r_square)); |
197 | } |
198 | |
199 | /// Parses a '?' token. |
200 | ParseResult parseQuestion() override { |
201 | return parser.parseToken(expectedToken: Token::question, message: "expected '?'"); |
202 | } |
203 | |
204 | /// Parses a '?' if present. |
205 | ParseResult parseOptionalQuestion() override { |
206 | return success(IsSuccess: parser.consumeIf(kind: Token::question)); |
207 | } |
208 | |
209 | /// Parses a '/' token. |
210 | ParseResult parseSlash() override { |
211 | return parser.parseToken(expectedToken: Token::slash, message: "expected '/'"); |
212 | } |
213 | |
214 | /// Parses a '/' if present. |
215 | ParseResult parseOptionalSlash() override { |
216 | return success(IsSuccess: parser.consumeIf(kind: Token::slash)); |
217 | } |
218 | |
219 | /// Parses a '*' token. |
220 | ParseResult parseStar() override { |
221 | return parser.parseToken(expectedToken: Token::star, message: "expected '*'"); |
222 | } |
223 | |
224 | /// Parses a '*' if present. |
225 | ParseResult parseOptionalStar() override { |
226 | return success(IsSuccess: parser.consumeIf(kind: Token::star)); |
227 | } |
228 | |
229 | /// Parses a '+' token. |
230 | ParseResult parsePlus() override { |
231 | return parser.parseToken(expectedToken: Token::plus, message: "expected '+'"); |
232 | } |
233 | |
234 | /// Parses a '+' token if present. |
235 | ParseResult parseOptionalPlus() override { |
236 | return success(IsSuccess: parser.consumeIf(kind: Token::plus)); |
237 | } |
238 | |
239 | /// Parses a '-' token. |
240 | ParseResult parseMinus() override { |
241 | return parser.parseToken(expectedToken: Token::minus, message: "expected '-'"); |
242 | } |
243 | |
244 | /// Parses a '-' token if present. |
245 | ParseResult parseOptionalMinus() override { |
246 | return success(IsSuccess: parser.consumeIf(kind: Token::minus)); |
247 | } |
248 | |
249 | /// Parse a '|' token. |
250 | ParseResult parseVerticalBar() override { |
251 | return parser.parseToken(expectedToken: Token::vertical_bar, message: "expected '|'"); |
252 | } |
253 | |
254 | /// Parse a '|' token if present. |
255 | ParseResult parseOptionalVerticalBar() override { |
256 | return success(IsSuccess: parser.consumeIf(kind: Token::vertical_bar)); |
257 | } |
258 | |
259 | /// Parses a quoted string token if present. |
260 | ParseResult parseOptionalString(std::string *string) override { |
261 | return parser.parseOptionalString(string); |
262 | } |
263 | |
264 | /// Parses a Base64 encoded string of bytes. |
265 | ParseResult parseBase64Bytes(std::vector<char> *bytes) override { |
266 | auto loc = getCurrentLocation(); |
267 | if (!parser.getToken().is(k: Token::string)) |
268 | return emitError(loc, message: "expected string"); |
269 | |
270 | if (bytes) { |
271 | // decodeBase64 doesn't modify its input so we can use the token spelling |
272 | // and just slice off the quotes/whitespaces if there are any. Whitespace |
273 | // and quotes cannot appear as part of a (standard) base64 encoded string, |
274 | // so this is safe to do. |
275 | StringRef b64QuotedString = parser.getTokenSpelling(); |
276 | StringRef b64String = |
277 | b64QuotedString.ltrim(Chars: "\" \t\n\v\f\r").rtrim(Chars: "\" \t\n\v\f\r"); |
278 | if (auto err = llvm::decodeBase64(Input: b64String, Output&: *bytes)) |
279 | return emitError(loc, message: toString(E: std::move(err))); |
280 | } |
281 | |
282 | parser.consumeToken(); |
283 | return success(); |
284 | } |
285 | |
286 | /// Parse a floating point value with given semantics from the stream. Since |
287 | /// this implementation parses the string as double precision and only |
288 | /// afterwards converts the value to the requested semantic, precision may be |
289 | /// lost. |
290 | ParseResult parseFloat(const llvm::fltSemantics &semantics, |
291 | APFloat &result) override { |
292 | bool isNegative = parser.consumeIf(kind: Token::minus); |
293 | Token curTok = parser.getToken(); |
294 | std::optional<APFloat> apResult; |
295 | if (failed(Result: parser.parseFloatFromLiteral(result&: apResult, tok: curTok, isNegative, |
296 | semantics))) |
297 | return failure(); |
298 | parser.consumeToken(); |
299 | result = *apResult; |
300 | return success(); |
301 | } |
302 | |
303 | /// Parse a floating point value from the stream. |
304 | ParseResult parseFloat(double &result) override { |
305 | llvm::APFloat apResult(0.0); |
306 | if (parseFloat(APFloat::IEEEdouble(), apResult)) |
307 | return failure(); |
308 | |
309 | result = apResult.convertToDouble(); |
310 | return success(); |
311 | } |
312 | |
313 | /// Parse an optional integer value from the stream. |
314 | OptionalParseResult parseOptionalInteger(APInt &result) override { |
315 | return parser.parseOptionalInteger(result); |
316 | } |
317 | |
318 | /// Parse an optional integer value from the stream. |
319 | OptionalParseResult parseOptionalDecimalInteger(APInt &result) override { |
320 | return parser.parseOptionalDecimalInteger(result); |
321 | } |
322 | |
323 | /// Parse a list of comma-separated items with an optional delimiter. If a |
324 | /// delimiter is provided, then an empty list is allowed. If not, then at |
325 | /// least one element will be parsed. |
326 | ParseResult parseCommaSeparatedList(Delimiter delimiter, |
327 | function_ref<ParseResult()> parseElt, |
328 | StringRef contextMessage) override { |
329 | return parser.parseCommaSeparatedList(delimiter, parseElementFn: parseElt, contextMessage); |
330 | } |
331 | |
332 | //===--------------------------------------------------------------------===// |
333 | // Keyword Parsing |
334 | //===--------------------------------------------------------------------===// |
335 | |
336 | ParseResult parseKeyword(StringRef keyword, const Twine &msg) override { |
337 | if (parser.getToken().isCodeCompletion()) |
338 | return parser.codeCompleteExpectedTokens(tokens: keyword); |
339 | |
340 | auto loc = getCurrentLocation(); |
341 | if (parseOptionalKeyword(keyword)) |
342 | return emitError(loc, message: "expected '") << keyword << "'"<< msg; |
343 | return success(); |
344 | } |
345 | using AsmParser::parseKeyword; |
346 | |
347 | /// Parse the given keyword if present. |
348 | ParseResult parseOptionalKeyword(StringRef keyword) override { |
349 | if (parser.getToken().isCodeCompletion()) |
350 | return parser.codeCompleteOptionalTokens(tokens: keyword); |
351 | |
352 | // Check that the current token has the same spelling. |
353 | if (!parser.isCurrentTokenAKeyword() || |
354 | parser.getTokenSpelling() != keyword) |
355 | return failure(); |
356 | parser.consumeToken(); |
357 | return success(); |
358 | } |
359 | |
360 | /// Parse a keyword, if present, into 'keyword'. |
361 | ParseResult parseOptionalKeyword(StringRef *keyword) override { |
362 | return parser.parseOptionalKeyword(keyword); |
363 | } |
364 | |
365 | /// Parse a keyword if it is one of the 'allowedKeywords'. |
366 | ParseResult |
367 | parseOptionalKeyword(StringRef *keyword, |
368 | ArrayRef<StringRef> allowedKeywords) override { |
369 | if (parser.getToken().isCodeCompletion()) |
370 | return parser.codeCompleteOptionalTokens(tokens: allowedKeywords); |
371 | |
372 | // Check that the current token is a keyword. |
373 | if (!parser.isCurrentTokenAKeyword()) |
374 | return failure(); |
375 | |
376 | StringRef currentKeyword = parser.getTokenSpelling(); |
377 | if (llvm::is_contained(Range&: allowedKeywords, Element: currentKeyword)) { |
378 | *keyword = currentKeyword; |
379 | parser.consumeToken(); |
380 | return success(); |
381 | } |
382 | |
383 | return failure(); |
384 | } |
385 | |
386 | /// Parse an optional keyword or string and set instance into 'result'.` |
387 | ParseResult parseOptionalKeywordOrString(std::string *result) override { |
388 | return parser.parseOptionalKeywordOrString(result); |
389 | } |
390 | |
391 | //===--------------------------------------------------------------------===// |
392 | // Attribute Parsing |
393 | //===--------------------------------------------------------------------===// |
394 | |
395 | /// Parse an arbitrary attribute and return it in result. |
396 | ParseResult parseAttribute(Attribute &result, Type type) override { |
397 | result = parser.parseAttribute(type); |
398 | return success(IsSuccess: static_cast<bool>(result)); |
399 | } |
400 | |
401 | /// Parse a custom attribute with the provided callback, unless the next |
402 | /// token is `#`, in which case the generic parser is invoked. |
403 | ParseResult parseCustomAttributeWithFallback( |
404 | Attribute &result, Type type, |
405 | function_ref<ParseResult(Attribute &result, Type type)> parseAttribute) |
406 | override { |
407 | if (parser.getToken().isNot(k: Token::hash_identifier)) |
408 | return parseAttribute(result, type); |
409 | result = parser.parseAttribute(type); |
410 | return success(IsSuccess: static_cast<bool>(result)); |
411 | } |
412 | |
413 | /// Parse a custom attribute with the provided callback, unless the next |
414 | /// token is `#`, in which case the generic parser is invoked. |
415 | ParseResult parseCustomTypeWithFallback( |
416 | Type &result, |
417 | function_ref<ParseResult(Type &result)> parseType) override { |
418 | if (parser.getToken().isNot(k: Token::exclamation_identifier)) |
419 | return parseType(result); |
420 | result = parser.parseType(); |
421 | return success(IsSuccess: static_cast<bool>(result)); |
422 | } |
423 | |
424 | OptionalParseResult parseOptionalAttribute(Attribute &result, |
425 | Type type) override { |
426 | return parser.parseOptionalAttribute(attribute&: result, type); |
427 | } |
428 | OptionalParseResult parseOptionalAttribute(ArrayAttr &result, |
429 | Type type) override { |
430 | return parser.parseOptionalAttribute(attribute&: result, type); |
431 | } |
432 | OptionalParseResult parseOptionalAttribute(StringAttr &result, |
433 | Type type) override { |
434 | return parser.parseOptionalAttribute(attribute&: result, type); |
435 | } |
436 | OptionalParseResult parseOptionalAttribute(SymbolRefAttr &result, |
437 | Type type) override { |
438 | return parser.parseOptionalAttribute(result, type); |
439 | } |
440 | |
441 | /// Parse a named dictionary into 'result' if it is present. |
442 | ParseResult parseOptionalAttrDict(NamedAttrList &result) override { |
443 | if (parser.getToken().isNot(k: Token::l_brace)) |
444 | return success(); |
445 | return parser.parseAttributeDict(attributes&: result); |
446 | } |
447 | |
448 | /// Parse a named dictionary into 'result' if the `attributes` keyword is |
449 | /// present. |
450 | ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result) override { |
451 | if (failed(parseOptionalKeyword("attributes"))) |
452 | return success(); |
453 | return parser.parseAttributeDict(attributes&: result); |
454 | } |
455 | |
456 | /// Parse an affine map instance into 'map'. |
457 | ParseResult parseAffineMap(AffineMap &map) override { |
458 | return parser.parseAffineMapReference(map); |
459 | } |
460 | |
461 | /// Parse an affine expr instance into 'expr' using the already computed |
462 | /// mapping from symbols to affine expressions in 'symbolSet'. |
463 | ParseResult |
464 | parseAffineExpr(ArrayRef<std::pair<StringRef, AffineExpr>> symbolSet, |
465 | AffineExpr &expr) override { |
466 | return parser.parseAffineExprReference(symbolSet, expr); |
467 | } |
468 | |
469 | /// Parse an integer set instance into 'set'. |
470 | ParseResult parseIntegerSet(IntegerSet &set) override { |
471 | return parser.parseIntegerSetReference(set); |
472 | } |
473 | |
474 | //===--------------------------------------------------------------------===// |
475 | // Identifier Parsing |
476 | //===--------------------------------------------------------------------===// |
477 | |
478 | /// Parse an optional @-identifier and store it (without the '@' symbol) in a |
479 | /// string attribute named 'attrName'. |
480 | ParseResult parseOptionalSymbolName(StringAttr &result) override { |
481 | Token atToken = parser.getToken(); |
482 | if (atToken.isNot(k: Token::at_identifier)) |
483 | return failure(); |
484 | |
485 | result = getBuilder().getStringAttr(atToken.getSymbolReference()); |
486 | parser.consumeToken(); |
487 | |
488 | // If we are populating the assembly parser state, record this as a symbol |
489 | // reference. |
490 | if (parser.getState().asmState) { |
491 | parser.getState().asmState->addUses(SymbolRefAttr::get(result), |
492 | atToken.getLocRange()); |
493 | } |
494 | return success(); |
495 | } |
496 | |
497 | //===--------------------------------------------------------------------===// |
498 | // Resource Parsing |
499 | //===--------------------------------------------------------------------===// |
500 | |
501 | /// Parse a handle to a resource within the assembly format. |
502 | FailureOr<AsmDialectResourceHandle> |
503 | parseResourceHandle(Dialect *dialect) override { |
504 | const auto *interface = dyn_cast<OpAsmDialectInterface>(Val: dialect); |
505 | if (!interface) { |
506 | return parser.emitError() << "dialect '"<< dialect->getNamespace() |
507 | << "' does not expect resource handles"; |
508 | } |
509 | std::string resourceName; |
510 | return parser.parseResourceHandle(dialect: interface, name&: resourceName); |
511 | } |
512 | |
513 | //===--------------------------------------------------------------------===// |
514 | // Type Parsing |
515 | //===--------------------------------------------------------------------===// |
516 | |
517 | /// Parse a type. |
518 | ParseResult parseType(Type &result) override { |
519 | return failure(IsFailure: !(result = parser.parseType())); |
520 | } |
521 | |
522 | /// Parse an optional type. |
523 | OptionalParseResult parseOptionalType(Type &result) override { |
524 | return parser.parseOptionalType(type&: result); |
525 | } |
526 | |
527 | /// Parse an arrow followed by a type list. |
528 | ParseResult parseArrowTypeList(SmallVectorImpl<Type> &result) override { |
529 | if (parseArrow() || parser.parseFunctionResultTypes(elements&: result)) |
530 | return failure(); |
531 | return success(); |
532 | } |
533 | |
534 | /// Parse an optional arrow followed by a type list. |
535 | ParseResult |
536 | parseOptionalArrowTypeList(SmallVectorImpl<Type> &result) override { |
537 | if (!parser.consumeIf(kind: Token::arrow)) |
538 | return success(); |
539 | return parser.parseFunctionResultTypes(elements&: result); |
540 | } |
541 | |
542 | /// Parse a colon followed by a type. |
543 | ParseResult parseColonType(Type &result) override { |
544 | return failure(IsFailure: parser.parseToken(expectedToken: Token::colon, message: "expected ':'") || |
545 | !(result = parser.parseType())); |
546 | } |
547 | |
548 | /// Parse a colon followed by a type list, which must have at least one type. |
549 | ParseResult parseColonTypeList(SmallVectorImpl<Type> &result) override { |
550 | if (parser.parseToken(expectedToken: Token::colon, message: "expected ':'")) |
551 | return failure(); |
552 | return parser.parseTypeListNoParens(elements&: result); |
553 | } |
554 | |
555 | /// Parse an optional colon followed by a type list, which if present must |
556 | /// have at least one type. |
557 | ParseResult |
558 | parseOptionalColonTypeList(SmallVectorImpl<Type> &result) override { |
559 | if (!parser.consumeIf(kind: Token::colon)) |
560 | return success(); |
561 | return parser.parseTypeListNoParens(elements&: result); |
562 | } |
563 | |
564 | ParseResult parseDimensionList(SmallVectorImpl<int64_t> &dimensions, |
565 | bool allowDynamic, |
566 | bool withTrailingX) override { |
567 | return parser.parseDimensionListRanked(dimensions, allowDynamic, |
568 | withTrailingX); |
569 | } |
570 | |
571 | ParseResult parseXInDimensionList() override { |
572 | return parser.parseXInDimensionList(); |
573 | } |
574 | |
575 | LogicalResult pushCyclicParsing(const void *opaquePointer) override { |
576 | return success(IsSuccess: parser.getState().cyclicParsingStack.insert(X: opaquePointer)); |
577 | } |
578 | |
579 | void popCyclicParsing() override { |
580 | parser.getState().cyclicParsingStack.pop_back(); |
581 | } |
582 | |
583 | //===--------------------------------------------------------------------===// |
584 | // Code Completion |
585 | //===--------------------------------------------------------------------===// |
586 | |
587 | /// Parse a keyword, or an empty string if the current location signals a code |
588 | /// completion. |
589 | ParseResult parseKeywordOrCompletion(StringRef *keyword) override { |
590 | Token tok = parser.getToken(); |
591 | if (tok.isCodeCompletion() && tok.getSpelling().empty()) { |
592 | *keyword = ""; |
593 | return success(); |
594 | } |
595 | return parseKeyword(keyword); |
596 | } |
597 | |
598 | /// Signal the code completion of a set of expected tokens. |
599 | void codeCompleteExpectedTokens(ArrayRef<StringRef> tokens) override { |
600 | Token tok = parser.getToken(); |
601 | if (tok.isCodeCompletion() && tok.getSpelling().empty()) |
602 | (void)parser.codeCompleteExpectedTokens(tokens); |
603 | } |
604 | |
605 | protected: |
606 | /// The source location of the dialect symbol. |
607 | SMLoc nameLoc; |
608 | |
609 | /// The main parser. |
610 | Parser &parser; |
611 | |
612 | /// A flag that indicates if any errors were emitted during parsing. |
613 | bool emittedError = false; |
614 | }; |
615 | } // namespace detail |
616 | } // namespace mlir |
617 | |
618 | #endif // MLIR_LIB_ASMPARSER_ASMPARSERIMPL_H |
619 |
Definitions
- AsmParserImpl
- AsmParserImpl
- ~AsmParserImpl
- getNameLoc
- didEmitError
- emitError
- getBuilder
- getCurrentLocation
- getEncodedSourceLoc
- parseArrow
- parseOptionalArrow
- parseLBrace
- parseOptionalLBrace
- parseRBrace
- parseOptionalRBrace
- parseColon
- parseOptionalColon
- parseComma
- parseOptionalComma
- parseEllipsis
- parseOptionalEllipsis
- parseEqual
- parseOptionalEqual
- parseLess
- parseOptionalLess
- parseGreater
- parseOptionalGreater
- parseLParen
- parseOptionalLParen
- parseRParen
- parseOptionalRParen
- parseLSquare
- parseOptionalLSquare
- parseRSquare
- parseOptionalRSquare
- parseQuestion
- parseOptionalQuestion
- parseSlash
- parseOptionalSlash
- parseStar
- parseOptionalStar
- parsePlus
- parseOptionalPlus
- parseMinus
- parseOptionalMinus
- parseVerticalBar
- parseOptionalVerticalBar
- parseOptionalString
- parseBase64Bytes
- parseFloat
- parseFloat
- parseOptionalInteger
- parseOptionalDecimalInteger
- parseCommaSeparatedList
- parseKeyword
- parseOptionalKeyword
- parseOptionalKeyword
- parseOptionalKeyword
- parseOptionalKeywordOrString
- parseAttribute
- parseCustomAttributeWithFallback
- parseCustomTypeWithFallback
- parseOptionalAttribute
- parseOptionalAttribute
- parseOptionalAttribute
- parseOptionalAttribute
- parseOptionalAttrDict
- parseOptionalAttrDictWithKeyword
- parseAffineMap
- parseAffineExpr
- parseIntegerSet
- parseOptionalSymbolName
- parseResourceHandle
- parseType
- parseOptionalType
- parseArrowTypeList
- parseOptionalArrowTypeList
- parseColonType
- parseColonTypeList
- parseOptionalColonTypeList
- parseDimensionList
- parseXInDimensionList
- pushCyclicParsing
- popCyclicParsing
- parseKeywordOrCompletion
Learn to use CMake with our Intro Training
Find out more