#ifndef MLIR_LIB_ASMPARSER_ASMPARSERIMPL_H
#define MLIR_LIB_ASMPARSER_ASMPARSERIMPL_H
#include "Parser.h"
#include "mlir/AsmParser/AsmParserState.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/OpImplementation.h"
#include "llvm/Support/Base64.h"
#include <optional>
namespace mlir {
namespace detail {
template <typename BaseT>
class AsmParserImpl : public BaseT {
public:
AsmParserImpl(SMLoc nameLoc, Parser &parser)
: nameLoc(nameLoc), parser(parser) {}
~AsmParserImpl() override = default;
SMLoc getNameLoc() const override { return nameLoc; }
bool didEmitError() const { return emittedError; }
InFlightDiagnostic emitError(SMLoc loc, const Twine &message) override {
emittedError = true;
return parser.emitError(loc, message);
}
Builder &getBuilder() const override { return parser.builder; }
SMLoc getCurrentLocation() override { return parser.getToken().getLoc(); }
Location getEncodedSourceLoc(SMLoc loc) override {
return parser.getEncodedSourceLocation(loc);
}
using Delimiter = AsmParser::Delimiter;
ParseResult parseArrow() override {
return parser.parseToken(Token::arrow, "expected '->'");
}
ParseResult parseOptionalArrow() override {
return success(parser.consumeIf(Token::arrow));
}
ParseResult parseLBrace() override {
return parser.parseToken(Token::l_brace, "expected '{'");
}
ParseResult parseOptionalLBrace() override {
return success(parser.consumeIf(Token::l_brace));
}
ParseResult parseRBrace() override {
return parser.parseToken(Token::r_brace, "expected '}'");
}
ParseResult parseOptionalRBrace() override {
return success(parser.consumeIf(Token::r_brace));
}
ParseResult parseColon() override {
return parser.parseToken(Token::colon, "expected ':'");
}
ParseResult parseOptionalColon() override {
return success(parser.consumeIf(Token::colon));
}
ParseResult parseComma() override {
return parser.parseToken(Token::comma, "expected ','");
}
ParseResult parseOptionalComma() override {
return success(parser.consumeIf(Token::comma));
}
ParseResult parseEllipsis() override {
return parser.parseToken(Token::ellipsis, "expected '...'");
}
ParseResult parseOptionalEllipsis() override {
return success(parser.consumeIf(Token::ellipsis));
}
ParseResult parseEqual() override {
return parser.parseToken(Token::equal, "expected '='");
}
ParseResult parseOptionalEqual() override {
return success(parser.consumeIf(Token::equal));
}
ParseResult parseLess() override {
return parser.parseToken(Token::less, "expected '<'");
}
ParseResult parseOptionalLess() override {
return success(parser.consumeIf(Token::less));
}
ParseResult parseGreater() override {
return parser.parseToken(Token::greater, "expected '>'");
}
ParseResult parseOptionalGreater() override {
return success(parser.consumeIf(Token::greater));
}
ParseResult parseLParen() override {
return parser.parseToken(Token::l_paren, "expected '('");
}
ParseResult parseOptionalLParen() override {
return success(parser.consumeIf(Token::l_paren));
}
ParseResult parseRParen() override {
return parser.parseToken(Token::r_paren, "expected ')'");
}
ParseResult parseOptionalRParen() override {
return success(parser.consumeIf(Token::r_paren));
}
ParseResult parseLSquare() override {
return parser.parseToken(Token::l_square, "expected '['");
}
ParseResult parseOptionalLSquare() override {
return success(parser.consumeIf(Token::l_square));
}
ParseResult parseRSquare() override {
return parser.parseToken(Token::r_square, "expected ']'");
}
ParseResult parseOptionalRSquare() override {
return success(parser.consumeIf(Token::r_square));
}
ParseResult parseQuestion() override {
return parser.parseToken(Token::question, "expected '?'");
}
ParseResult parseOptionalQuestion() override {
return success(parser.consumeIf(Token::question));
}
ParseResult parseStar() override {
return parser.parseToken(Token::star, "expected '*'");
}
ParseResult parseOptionalStar() override {
return success(parser.consumeIf(Token::star));
}
ParseResult parsePlus() override {
return parser.parseToken(Token::plus, "expected '+'");
}
ParseResult parseOptionalPlus() override {
return success(parser.consumeIf(Token::plus));
}
ParseResult parseVerticalBar() override {
return parser.parseToken(Token::vertical_bar, "expected '|'");
}
ParseResult parseOptionalVerticalBar() override {
return success(parser.consumeIf(Token::vertical_bar));
}
ParseResult parseOptionalString(std::string *string) override {
if (!parser.getToken().is(Token::string))
return failure();
if (string)
*string = parser.getToken().getStringValue();
parser.consumeToken();
return success();
}
ParseResult parseBase64Bytes(std::vector<char> *bytes) override {
auto loc = getCurrentLocation();
if (!parser.getToken().is(Token::string))
return emitError(loc, "expected string");
if (bytes) {
StringRef b64QuotedString = parser.getTokenSpelling();
StringRef b64String =
b64QuotedString.ltrim("\" \t\n\v\f\r").rtrim("\" \t\n\v\f\r");
if (auto err = llvm::decodeBase64(b64String, *bytes))
return emitError(loc, toString(std::move(err)));
}
parser.consumeToken();
return success();
}
ParseResult parseFloat(double &result) override {
bool isNegative = parser.consumeIf(Token::minus);
Token curTok = parser.getToken();
SMLoc loc = curTok.getLoc();
if (curTok.is(Token::floatliteral)) {
auto val = curTok.getFloatingPointValue();
if (!val)
return emitError(loc, "floating point value too large");
parser.consumeToken(Token::floatliteral);
result = isNegative ? -*val : *val;
return success();
}
if (curTok.is(Token::integer)) {
std::optional<APFloat> apResult;
if (failed(parser.parseFloatFromIntegerLiteral(
apResult, curTok, isNegative, APFloat::IEEEdouble(),
64)))
return failure();
parser.consumeToken(Token::integer);
result = apResult->convertToDouble();
return success();
}
return emitError(loc, "expected floating point literal");
}
OptionalParseResult parseOptionalInteger(APInt &result) override {
return parser.parseOptionalInteger(result);
}
ParseResult parseCommaSeparatedList(Delimiter delimiter,
function_ref<ParseResult()> parseElt,
StringRef contextMessage) override {
return parser.parseCommaSeparatedList(delimiter, parseElt, contextMessage);
}
ParseResult parseKeyword(StringRef keyword, const Twine &msg) override {
if (parser.getToken().isCodeCompletion())
return parser.codeCompleteExpectedTokens(keyword);
auto loc = getCurrentLocation();
if (parseOptionalKeyword(keyword))
return emitError(loc, "expected '") << keyword << "'" << msg;
return success();
}
using AsmParser::parseKeyword;
ParseResult parseOptionalKeyword(StringRef keyword) override {
if (parser.getToken().isCodeCompletion())
return parser.codeCompleteOptionalTokens(keyword);
if (!parser.isCurrentTokenAKeyword() ||
parser.getTokenSpelling() != keyword)
return failure();
parser.consumeToken();
return success();
}
ParseResult parseOptionalKeyword(StringRef *keyword) override {
if (!parser.isCurrentTokenAKeyword())
return failure();
*keyword = parser.getTokenSpelling();
parser.consumeToken();
return success();
}
ParseResult
parseOptionalKeyword(StringRef *keyword,
ArrayRef<StringRef> allowedKeywords) override {
if (parser.getToken().isCodeCompletion())
return parser.codeCompleteOptionalTokens(allowedKeywords);
if (!parser.isCurrentTokenAKeyword())
return failure();
StringRef currentKeyword = parser.getTokenSpelling();
if (llvm::is_contained(allowedKeywords, currentKeyword)) {
*keyword = currentKeyword;
parser.consumeToken();
return success();
}
return failure();
}
ParseResult parseOptionalKeywordOrString(std::string *result) override {
StringRef keyword;
if (succeeded(parseOptionalKeyword(&keyword))) {
*result = keyword.str();
return success();
}
return parseOptionalString(result);
}
ParseResult parseAttribute(Attribute &result, Type type) override {
result = parser.parseAttribute(type);
return success(static_cast<bool>(result));
}
ParseResult parseCustomAttributeWithFallback(
Attribute &result, Type type,
function_ref<ParseResult(Attribute &result, Type type)> parseAttribute)
override {
if (parser.getToken().isNot(Token::hash_identifier))
return parseAttribute(result, type);
result = parser.parseAttribute(type);
return success(static_cast<bool>(result));
}
ParseResult parseCustomTypeWithFallback(
Type &result,
function_ref<ParseResult(Type &result)> parseType) override {
if (parser.getToken().isNot(Token::exclamation_identifier))
return parseType(result);
result = parser.parseType();
return success(static_cast<bool>(result));
}
OptionalParseResult parseOptionalAttribute(Attribute &result,
Type type) override {
return parser.parseOptionalAttribute(result, type);
}
OptionalParseResult parseOptionalAttribute(ArrayAttr &result,
Type type) override {
return parser.parseOptionalAttribute(result, type);
}
OptionalParseResult parseOptionalAttribute(StringAttr &result,
Type type) override {
return parser.parseOptionalAttribute(result, type);
}
OptionalParseResult parseOptionalAttribute(SymbolRefAttr &result,
Type type) override {
return parser.parseOptionalAttribute(result, type);
}
ParseResult parseOptionalAttrDict(NamedAttrList &result) override {
if (parser.getToken().isNot(Token::l_brace))
return success();
return parser.parseAttributeDict(result);
}
ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result) override {
if (failed(parseOptionalKeyword("attributes")))
return success();
return parser.parseAttributeDict(result);
}
ParseResult parseAffineMap(AffineMap &map) override {
return parser.parseAffineMapReference(map);
}
ParseResult
parseAffineExpr(ArrayRef<std::pair<StringRef, AffineExpr>> symbolSet,
AffineExpr &expr) override {
return parser.parseAffineExprReference(symbolSet, expr);
}
ParseResult parseIntegerSet(IntegerSet &set) override {
return parser.parseIntegerSetReference(set);
}
ParseResult parseOptionalSymbolName(StringAttr &result) override {
Token atToken = parser.getToken();
if (atToken.isNot(Token::at_identifier))
return failure();
result = getBuilder().getStringAttr(atToken.getSymbolReference());
parser.consumeToken();
if (parser.getState().asmState) {
parser.getState().asmState->addUses(SymbolRefAttr::get(result),
atToken.getLocRange());
}
return success();
}
FailureOr<AsmDialectResourceHandle>
parseResourceHandle(Dialect *dialect) override {
const auto *interface = dyn_cast<OpAsmDialectInterface>(dialect);
if (!interface) {
return parser.emitError() << "dialect '" << dialect->getNamespace()
<< "' does not expect resource handles";
}
StringRef resourceName;
return parser.parseResourceHandle(interface, resourceName);
}
ParseResult parseType(Type &result) override {
return failure(!(result = parser.parseType()));
}
OptionalParseResult parseOptionalType(Type &result) override {
return parser.parseOptionalType(result);
}
ParseResult parseArrowTypeList(SmallVectorImpl<Type> &result) override {
if (parseArrow() || parser.parseFunctionResultTypes(result))
return failure();
return success();
}
ParseResult
parseOptionalArrowTypeList(SmallVectorImpl<Type> &result) override {
if (!parser.consumeIf(Token::arrow))
return success();
return parser.parseFunctionResultTypes(result);
}
ParseResult parseColonType(Type &result) override {
return failure(parser.parseToken(Token::colon, "expected ':'") ||
!(result = parser.parseType()));
}
ParseResult parseColonTypeList(SmallVectorImpl<Type> &result) override {
if (parser.parseToken(Token::colon, "expected ':'"))
return failure();
return parser.parseTypeListNoParens(result);
}
ParseResult
parseOptionalColonTypeList(SmallVectorImpl<Type> &result) override {
if (!parser.consumeIf(Token::colon))
return success();
return parser.parseTypeListNoParens(result);
}
ParseResult parseDimensionList(SmallVectorImpl<int64_t> &dimensions,
bool allowDynamic,
bool withTrailingX) override {
return parser.parseDimensionListRanked(dimensions, allowDynamic,
withTrailingX);
}
ParseResult parseXInDimensionList() override {
return parser.parseXInDimensionList();
}
ParseResult parseKeywordOrCompletion(StringRef *keyword) override {
Token tok = parser.getToken();
if (tok.isCodeCompletion() && tok.getSpelling().empty()) {
*keyword = "";
return success();
}
return parseKeyword(keyword);
}
void codeCompleteExpectedTokens(ArrayRef<StringRef> tokens) override {
Token tok = parser.getToken();
if (tok.isCodeCompletion() && tok.getSpelling().empty())
(void)parser.codeCompleteExpectedTokens(tokens);
}
protected:
SMLoc nameLoc;
Parser &parser;
bool emittedError = false;
};
}
}
#endif