[clang][Driver] Support simplified triple versions for config files (#111387)
[llvm-project.git] / mlir / lib / AsmParser / AsmParserImpl.h
blobd5b72d63813a4e4d643b33b800539cf0db02dce9
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 //===----------------------------------------------------------------------===//
9 #ifndef MLIR_LIB_ASMPARSER_ASMPARSERIMPL_H
10 #define MLIR_LIB_ASMPARSER_ASMPARSERIMPL_H
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>
19 namespace mlir {
20 namespace detail {
21 //===----------------------------------------------------------------------===//
22 // AsmParserImpl
23 //===----------------------------------------------------------------------===//
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;
34 /// Return the location of the original name token.
35 SMLoc getNameLoc() const override { return nameLoc; }
37 //===--------------------------------------------------------------------===//
38 // Utilities
39 //===--------------------------------------------------------------------===//
41 /// Return if any errors were emitted during parsing.
42 bool didEmitError() const { return emittedError; }
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);
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; }
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(); }
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);
63 //===--------------------------------------------------------------------===//
64 // Token Parsing
65 //===--------------------------------------------------------------------===//
67 using Delimiter = AsmParser::Delimiter;
69 /// Parse a `->` token.
70 ParseResult parseArrow() override {
71 return parser.parseToken(Token::arrow, "expected '->'");
74 /// Parses a `->` if present.
75 ParseResult parseOptionalArrow() override {
76 return success(parser.consumeIf(Token::arrow));
79 /// Parse a '{' token.
80 ParseResult parseLBrace() override {
81 return parser.parseToken(Token::l_brace, "expected '{'");
84 /// Parse a '{' token if present
85 ParseResult parseOptionalLBrace() override {
86 return success(parser.consumeIf(Token::l_brace));
89 /// Parse a `}` token.
90 ParseResult parseRBrace() override {
91 return parser.parseToken(Token::r_brace, "expected '}'");
94 /// Parse a `}` token if present
95 ParseResult parseOptionalRBrace() override {
96 return success(parser.consumeIf(Token::r_brace));
99 /// Parse a `:` token.
100 ParseResult parseColon() override {
101 return parser.parseToken(Token::colon, "expected ':'");
104 /// Parse a `:` token if present.
105 ParseResult parseOptionalColon() override {
106 return success(parser.consumeIf(Token::colon));
109 /// Parse a `,` token.
110 ParseResult parseComma() override {
111 return parser.parseToken(Token::comma, "expected ','");
114 /// Parse a `,` token if present.
115 ParseResult parseOptionalComma() override {
116 return success(parser.consumeIf(Token::comma));
119 /// Parses a `...`.
120 ParseResult parseEllipsis() override {
121 return parser.parseToken(Token::ellipsis, "expected '...'");
124 /// Parses a `...` if present.
125 ParseResult parseOptionalEllipsis() override {
126 return success(parser.consumeIf(Token::ellipsis));
129 /// Parse a `=` token.
130 ParseResult parseEqual() override {
131 return parser.parseToken(Token::equal, "expected '='");
134 /// Parse a `=` token if present.
135 ParseResult parseOptionalEqual() override {
136 return success(parser.consumeIf(Token::equal));
139 /// Parse a '<' token.
140 ParseResult parseLess() override {
141 return parser.parseToken(Token::less, "expected '<'");
144 /// Parse a `<` token if present.
145 ParseResult parseOptionalLess() override {
146 return success(parser.consumeIf(Token::less));
149 /// Parse a '>' token.
150 ParseResult parseGreater() override {
151 return parser.parseToken(Token::greater, "expected '>'");
154 /// Parse a `>` token if present.
155 ParseResult parseOptionalGreater() override {
156 return success(parser.consumeIf(Token::greater));
159 /// Parse a `(` token.
160 ParseResult parseLParen() override {
161 return parser.parseToken(Token::l_paren, "expected '('");
164 /// Parses a '(' if present.
165 ParseResult parseOptionalLParen() override {
166 return success(parser.consumeIf(Token::l_paren));
169 /// Parse a `)` token.
170 ParseResult parseRParen() override {
171 return parser.parseToken(Token::r_paren, "expected ')'");
174 /// Parses a ')' if present.
175 ParseResult parseOptionalRParen() override {
176 return success(parser.consumeIf(Token::r_paren));
179 /// Parse a `[` token.
180 ParseResult parseLSquare() override {
181 return parser.parseToken(Token::l_square, "expected '['");
184 /// Parses a '[' if present.
185 ParseResult parseOptionalLSquare() override {
186 return success(parser.consumeIf(Token::l_square));
189 /// Parse a `]` token.
190 ParseResult parseRSquare() override {
191 return parser.parseToken(Token::r_square, "expected ']'");
194 /// Parses a ']' if present.
195 ParseResult parseOptionalRSquare() override {
196 return success(parser.consumeIf(Token::r_square));
199 /// Parses a '?' token.
200 ParseResult parseQuestion() override {
201 return parser.parseToken(Token::question, "expected '?'");
204 /// Parses a '?' if present.
205 ParseResult parseOptionalQuestion() override {
206 return success(parser.consumeIf(Token::question));
209 /// Parses a '*' token.
210 ParseResult parseStar() override {
211 return parser.parseToken(Token::star, "expected '*'");
214 /// Parses a '*' if present.
215 ParseResult parseOptionalStar() override {
216 return success(parser.consumeIf(Token::star));
219 /// Parses a '+' token.
220 ParseResult parsePlus() override {
221 return parser.parseToken(Token::plus, "expected '+'");
224 /// Parses a '+' token if present.
225 ParseResult parseOptionalPlus() override {
226 return success(parser.consumeIf(Token::plus));
229 /// Parses a '-' token.
230 ParseResult parseMinus() override {
231 return parser.parseToken(Token::minus, "expected '-'");
234 /// Parses a '-' token if present.
235 ParseResult parseOptionalMinus() override {
236 return success(parser.consumeIf(Token::minus));
239 /// Parse a '|' token.
240 ParseResult parseVerticalBar() override {
241 return parser.parseToken(Token::vertical_bar, "expected '|'");
244 /// Parse a '|' token if present.
245 ParseResult parseOptionalVerticalBar() override {
246 return success(parser.consumeIf(Token::vertical_bar));
249 /// Parses a quoted string token if present.
250 ParseResult parseOptionalString(std::string *string) override {
251 if (!parser.getToken().is(Token::string))
252 return failure();
254 if (string)
255 *string = parser.getToken().getStringValue();
256 parser.consumeToken();
257 return success();
260 /// Parses a Base64 encoded string of bytes.
261 ParseResult parseBase64Bytes(std::vector<char> *bytes) override {
262 auto loc = getCurrentLocation();
263 if (!parser.getToken().is(Token::string))
264 return emitError(loc, "expected string");
266 if (bytes) {
267 // decodeBase64 doesn't modify its input so we can use the token spelling
268 // and just slice off the quotes/whitespaces if there are any. Whitespace
269 // and quotes cannot appear as part of a (standard) base64 encoded string,
270 // so this is safe to do.
271 StringRef b64QuotedString = parser.getTokenSpelling();
272 StringRef b64String =
273 b64QuotedString.ltrim("\" \t\n\v\f\r").rtrim("\" \t\n\v\f\r");
274 if (auto err = llvm::decodeBase64(b64String, *bytes))
275 return emitError(loc, toString(std::move(err)));
278 parser.consumeToken();
279 return success();
282 /// Parse a floating point value with given semantics from the stream. Since
283 /// this implementation parses the string as double precision and only
284 /// afterwards converts the value to the requested semantic, precision may be
285 /// lost.
286 ParseResult parseFloat(const llvm::fltSemantics &semantics,
287 APFloat &result) override {
288 bool isNegative = parser.consumeIf(Token::minus);
289 Token curTok = parser.getToken();
290 std::optional<APFloat> apResult;
291 if (failed(parser.parseFloatFromLiteral(apResult, curTok, isNegative,
292 semantics)))
293 return failure();
294 parser.consumeToken();
295 result = *apResult;
296 return success();
299 /// Parse a floating point value from the stream.
300 ParseResult parseFloat(double &result) override {
301 llvm::APFloat apResult(0.0);
302 if (parseFloat(APFloat::IEEEdouble(), apResult))
303 return failure();
305 result = apResult.convertToDouble();
306 return success();
309 /// Parse an optional integer value from the stream.
310 OptionalParseResult parseOptionalInteger(APInt &result) override {
311 return parser.parseOptionalInteger(result);
314 /// Parse an optional integer value from the stream.
315 OptionalParseResult parseOptionalDecimalInteger(APInt &result) override {
316 return parser.parseOptionalDecimalInteger(result);
319 /// Parse a list of comma-separated items with an optional delimiter. If a
320 /// delimiter is provided, then an empty list is allowed. If not, then at
321 /// least one element will be parsed.
322 ParseResult parseCommaSeparatedList(Delimiter delimiter,
323 function_ref<ParseResult()> parseElt,
324 StringRef contextMessage) override {
325 return parser.parseCommaSeparatedList(delimiter, parseElt, contextMessage);
328 //===--------------------------------------------------------------------===//
329 // Keyword Parsing
330 //===--------------------------------------------------------------------===//
332 ParseResult parseKeyword(StringRef keyword, const Twine &msg) override {
333 if (parser.getToken().isCodeCompletion())
334 return parser.codeCompleteExpectedTokens(keyword);
336 auto loc = getCurrentLocation();
337 if (parseOptionalKeyword(keyword))
338 return emitError(loc, "expected '") << keyword << "'" << msg;
339 return success();
341 using AsmParser::parseKeyword;
343 /// Parse the given keyword if present.
344 ParseResult parseOptionalKeyword(StringRef keyword) override {
345 if (parser.getToken().isCodeCompletion())
346 return parser.codeCompleteOptionalTokens(keyword);
348 // Check that the current token has the same spelling.
349 if (!parser.isCurrentTokenAKeyword() ||
350 parser.getTokenSpelling() != keyword)
351 return failure();
352 parser.consumeToken();
353 return success();
356 /// Parse a keyword, if present, into 'keyword'.
357 ParseResult parseOptionalKeyword(StringRef *keyword) override {
358 // Check that the current token is a keyword.
359 if (!parser.isCurrentTokenAKeyword())
360 return failure();
362 *keyword = parser.getTokenSpelling();
363 parser.consumeToken();
364 return success();
367 /// Parse a keyword if it is one of the 'allowedKeywords'.
368 ParseResult
369 parseOptionalKeyword(StringRef *keyword,
370 ArrayRef<StringRef> allowedKeywords) override {
371 if (parser.getToken().isCodeCompletion())
372 return parser.codeCompleteOptionalTokens(allowedKeywords);
374 // Check that the current token is a keyword.
375 if (!parser.isCurrentTokenAKeyword())
376 return failure();
378 StringRef currentKeyword = parser.getTokenSpelling();
379 if (llvm::is_contained(allowedKeywords, currentKeyword)) {
380 *keyword = currentKeyword;
381 parser.consumeToken();
382 return success();
385 return failure();
388 /// Parse an optional keyword or string and set instance into 'result'.`
389 ParseResult parseOptionalKeywordOrString(std::string *result) override {
390 StringRef keyword;
391 if (succeeded(parseOptionalKeyword(&keyword))) {
392 *result = keyword.str();
393 return success();
396 return parseOptionalString(result);
399 //===--------------------------------------------------------------------===//
400 // Attribute Parsing
401 //===--------------------------------------------------------------------===//
403 /// Parse an arbitrary attribute and return it in result.
404 ParseResult parseAttribute(Attribute &result, Type type) override {
405 result = parser.parseAttribute(type);
406 return success(static_cast<bool>(result));
409 /// Parse a custom attribute with the provided callback, unless the next
410 /// token is `#`, in which case the generic parser is invoked.
411 ParseResult parseCustomAttributeWithFallback(
412 Attribute &result, Type type,
413 function_ref<ParseResult(Attribute &result, Type type)> parseAttribute)
414 override {
415 if (parser.getToken().isNot(Token::hash_identifier))
416 return parseAttribute(result, type);
417 result = parser.parseAttribute(type);
418 return success(static_cast<bool>(result));
421 /// Parse a custom attribute with the provided callback, unless the next
422 /// token is `#`, in which case the generic parser is invoked.
423 ParseResult parseCustomTypeWithFallback(
424 Type &result,
425 function_ref<ParseResult(Type &result)> parseType) override {
426 if (parser.getToken().isNot(Token::exclamation_identifier))
427 return parseType(result);
428 result = parser.parseType();
429 return success(static_cast<bool>(result));
432 OptionalParseResult parseOptionalAttribute(Attribute &result,
433 Type type) override {
434 return parser.parseOptionalAttribute(result, type);
436 OptionalParseResult parseOptionalAttribute(ArrayAttr &result,
437 Type type) override {
438 return parser.parseOptionalAttribute(result, type);
440 OptionalParseResult parseOptionalAttribute(StringAttr &result,
441 Type type) override {
442 return parser.parseOptionalAttribute(result, type);
444 OptionalParseResult parseOptionalAttribute(SymbolRefAttr &result,
445 Type type) override {
446 return parser.parseOptionalAttribute(result, type);
449 /// Parse a named dictionary into 'result' if it is present.
450 ParseResult parseOptionalAttrDict(NamedAttrList &result) override {
451 if (parser.getToken().isNot(Token::l_brace))
452 return success();
453 return parser.parseAttributeDict(result);
456 /// Parse a named dictionary into 'result' if the `attributes` keyword is
457 /// present.
458 ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result) override {
459 if (failed(parseOptionalKeyword("attributes")))
460 return success();
461 return parser.parseAttributeDict(result);
464 /// Parse an affine map instance into 'map'.
465 ParseResult parseAffineMap(AffineMap &map) override {
466 return parser.parseAffineMapReference(map);
469 /// Parse an affine expr instance into 'expr' using the already computed
470 /// mapping from symbols to affine expressions in 'symbolSet'.
471 ParseResult
472 parseAffineExpr(ArrayRef<std::pair<StringRef, AffineExpr>> symbolSet,
473 AffineExpr &expr) override {
474 return parser.parseAffineExprReference(symbolSet, expr);
477 /// Parse an integer set instance into 'set'.
478 ParseResult parseIntegerSet(IntegerSet &set) override {
479 return parser.parseIntegerSetReference(set);
482 //===--------------------------------------------------------------------===//
483 // Identifier Parsing
484 //===--------------------------------------------------------------------===//
486 /// Parse an optional @-identifier and store it (without the '@' symbol) in a
487 /// string attribute named 'attrName'.
488 ParseResult parseOptionalSymbolName(StringAttr &result) override {
489 Token atToken = parser.getToken();
490 if (atToken.isNot(Token::at_identifier))
491 return failure();
493 result = getBuilder().getStringAttr(atToken.getSymbolReference());
494 parser.consumeToken();
496 // If we are populating the assembly parser state, record this as a symbol
497 // reference.
498 if (parser.getState().asmState) {
499 parser.getState().asmState->addUses(SymbolRefAttr::get(result),
500 atToken.getLocRange());
502 return success();
505 //===--------------------------------------------------------------------===//
506 // Resource Parsing
507 //===--------------------------------------------------------------------===//
509 /// Parse a handle to a resource within the assembly format.
510 FailureOr<AsmDialectResourceHandle>
511 parseResourceHandle(Dialect *dialect) override {
512 const auto *interface = dyn_cast<OpAsmDialectInterface>(dialect);
513 if (!interface) {
514 return parser.emitError() << "dialect '" << dialect->getNamespace()
515 << "' does not expect resource handles";
517 StringRef resourceName;
518 return parser.parseResourceHandle(interface, resourceName);
521 //===--------------------------------------------------------------------===//
522 // Type Parsing
523 //===--------------------------------------------------------------------===//
525 /// Parse a type.
526 ParseResult parseType(Type &result) override {
527 return failure(!(result = parser.parseType()));
530 /// Parse an optional type.
531 OptionalParseResult parseOptionalType(Type &result) override {
532 return parser.parseOptionalType(result);
535 /// Parse an arrow followed by a type list.
536 ParseResult parseArrowTypeList(SmallVectorImpl<Type> &result) override {
537 if (parseArrow() || parser.parseFunctionResultTypes(result))
538 return failure();
539 return success();
542 /// Parse an optional arrow followed by a type list.
543 ParseResult
544 parseOptionalArrowTypeList(SmallVectorImpl<Type> &result) override {
545 if (!parser.consumeIf(Token::arrow))
546 return success();
547 return parser.parseFunctionResultTypes(result);
550 /// Parse a colon followed by a type.
551 ParseResult parseColonType(Type &result) override {
552 return failure(parser.parseToken(Token::colon, "expected ':'") ||
553 !(result = parser.parseType()));
556 /// Parse a colon followed by a type list, which must have at least one type.
557 ParseResult parseColonTypeList(SmallVectorImpl<Type> &result) override {
558 if (parser.parseToken(Token::colon, "expected ':'"))
559 return failure();
560 return parser.parseTypeListNoParens(result);
563 /// Parse an optional colon followed by a type list, which if present must
564 /// have at least one type.
565 ParseResult
566 parseOptionalColonTypeList(SmallVectorImpl<Type> &result) override {
567 if (!parser.consumeIf(Token::colon))
568 return success();
569 return parser.parseTypeListNoParens(result);
572 ParseResult parseDimensionList(SmallVectorImpl<int64_t> &dimensions,
573 bool allowDynamic,
574 bool withTrailingX) override {
575 return parser.parseDimensionListRanked(dimensions, allowDynamic,
576 withTrailingX);
579 ParseResult parseXInDimensionList() override {
580 return parser.parseXInDimensionList();
583 LogicalResult pushCyclicParsing(const void *opaquePointer) override {
584 return success(parser.getState().cyclicParsingStack.insert(opaquePointer));
587 void popCyclicParsing() override {
588 parser.getState().cyclicParsingStack.pop_back();
591 //===--------------------------------------------------------------------===//
592 // Code Completion
593 //===--------------------------------------------------------------------===//
595 /// Parse a keyword, or an empty string if the current location signals a code
596 /// completion.
597 ParseResult parseKeywordOrCompletion(StringRef *keyword) override {
598 Token tok = parser.getToken();
599 if (tok.isCodeCompletion() && tok.getSpelling().empty()) {
600 *keyword = "";
601 return success();
603 return parseKeyword(keyword);
606 /// Signal the code completion of a set of expected tokens.
607 void codeCompleteExpectedTokens(ArrayRef<StringRef> tokens) override {
608 Token tok = parser.getToken();
609 if (tok.isCodeCompletion() && tok.getSpelling().empty())
610 (void)parser.codeCompleteExpectedTokens(tokens);
613 protected:
614 /// The source location of the dialect symbol.
615 SMLoc nameLoc;
617 /// The main parser.
618 Parser &parser;
620 /// A flag that indicates if any errors were emitted during parsing.
621 bool emittedError = false;
623 } // namespace detail
624 } // namespace mlir
626 #endif // MLIR_LIB_ASMPARSER_ASMPARSERIMPL_H