diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h index 6efad01dec4cc..8b56d81c8eecc 100644 --- a/mlir/include/mlir/IR/OpImplementation.h +++ b/mlir/include/mlir/IR/OpImplementation.h @@ -656,6 +656,12 @@ class AsmParser { /// Parse a '+' token if present. virtual ParseResult parseOptionalPlus() = 0; + /// Parse a '/' token. + virtual ParseResult parseSlash() = 0; + + /// Parse a '/' token if present. + virtual ParseResult parseOptionalSlash() = 0; + /// Parse a '-' token. virtual ParseResult parseMinus() = 0; diff --git a/mlir/lib/AsmParser/AsmParserImpl.h b/mlir/lib/AsmParser/AsmParserImpl.h index 1f8fbfdd93568..eec2702cba343 100644 --- a/mlir/lib/AsmParser/AsmParserImpl.h +++ b/mlir/lib/AsmParser/AsmParserImpl.h @@ -206,6 +206,16 @@ class AsmParserImpl : public BaseT { return success(parser.consumeIf(Token::question)); } + /// Parses a '/' token. + ParseResult parseSlash() override { + return parser.parseToken(Token::slash, "expected '/'"); + } + + /// Parses a '/' if present. + ParseResult parseOptionalSlash() override { + return success(parser.consumeIf(Token::slash)); + } + /// Parses a '*' token. ParseResult parseStar() override { return parser.parseToken(Token::star, "expected '*'"); diff --git a/mlir/lib/AsmParser/Lexer.cpp b/mlir/lib/AsmParser/Lexer.cpp index b4189181a8495..751bd63e537f8 100644 --- a/mlir/lib/AsmParser/Lexer.cpp +++ b/mlir/lib/AsmParser/Lexer.cpp @@ -157,7 +157,7 @@ Token Lexer::lexToken() { skipComment(); continue; } - return emitError(tokStart, "unexpected character"); + return formToken(Token::slash, tokStart); case '@': return lexAtIdentifier(tokStart); diff --git a/mlir/lib/AsmParser/TokenKinds.def b/mlir/lib/AsmParser/TokenKinds.def index 49da8c3dea5fa..fe7c53753e156 100644 --- a/mlir/lib/AsmParser/TokenKinds.def +++ b/mlir/lib/AsmParser/TokenKinds.def @@ -70,6 +70,7 @@ TOK_PUNCTUATION(question, "?") TOK_PUNCTUATION(r_brace, "}") TOK_PUNCTUATION(r_paren, ")") TOK_PUNCTUATION(r_square, "]") +TOK_PUNCTUATION(slash, "/") TOK_PUNCTUATION(star, "*") TOK_PUNCTUATION(vertical_bar, "|") diff --git a/mlir/test/IR/parser.mlir b/mlir/test/IR/parser.mlir index bb19cb63b65a5..3bb6e38b4d613 100644 --- a/mlir/test/IR/parser.mlir +++ b/mlir/test/IR/parser.mlir @@ -1232,6 +1232,13 @@ func.func @parse_base64_test() { return } +// CHECK-LABEL: func @parse_slash_test +func.func @parse_slash_test() { + // CHECK: "test.slash_attr"() <{attr = #test.slash_attr<1 / 2>}> : () -> () + "test.slash_attr"() { attr = #test.slash_attr<1 / 2> } : () -> () + return +} + // CHECK-LABEL: func @"\22_string_symbol_reference\22" func.func @"\"_string_symbol_reference\""() { // CHECK: ref = @"\22_string_symbol_reference\22" diff --git a/mlir/test/lib/Dialect/Test/TestAttrDefs.td b/mlir/test/lib/Dialect/Test/TestAttrDefs.td index d42f469c39c69..4d825e2f0a8cc 100644 --- a/mlir/test/lib/Dialect/Test/TestAttrDefs.td +++ b/mlir/test/lib/Dialect/Test/TestAttrDefs.td @@ -418,4 +418,17 @@ def TestOpAsmAttrInterfaceTablegenDefaultAttr : Test_Attr<"TestOpAsmAttrInterfac let genMnemonicAlias = 1; } +// Test attribute containing a slash token +def SlashAttr: Test_Attr<"Slash">{ + let mnemonic = "slash_attr"; + + let parameters = ( + ins + "int":$lhs, + "int":$rhs + ); + + let hasCustomAssemblyFormat = 1; +} + #endif // TEST_ATTRDEFS diff --git a/mlir/test/lib/Dialect/Test/TestAttributes.cpp b/mlir/test/lib/Dialect/Test/TestAttributes.cpp index b36f246b83d76..80661e68754ce 100644 --- a/mlir/test/lib/Dialect/Test/TestAttributes.cpp +++ b/mlir/test/lib/Dialect/Test/TestAttributes.cpp @@ -497,6 +497,24 @@ getDynamicCustomAssemblyFormatAttr(TestDialect *testDialect) { std::move(parser), std::move(printer)); } +//===----------------------------------------------------------------------===// +// SlashAttr +//===----------------------------------------------------------------------===// + +Attribute SlashAttr::parse(AsmParser &parser, Type type) { + int lhs, rhs; + + if (parser.parseLess() || parser.parseInteger(lhs) || parser.parseSlash() || + parser.parseInteger(rhs) || parser.parseGreater()) + return Attribute(); + + return SlashAttr::get(parser.getContext(), lhs, rhs); +} + +void SlashAttr::print(AsmPrinter &printer) const { + printer << "<" << getLhs() << " / " << getRhs() << ">"; +} + //===----------------------------------------------------------------------===// // TestDialect //===----------------------------------------------------------------------===// diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index 4848e232472f0..43a0bdaf86cf3 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -324,6 +324,10 @@ def DenseArrayAttrOp : TEST_Op<"dense_array_attr"> { }]; } +def SlashAttrOp : TEST_Op<"slash_attr"> { + let arguments = (ins SlashAttr:$attr); +} + //===----------------------------------------------------------------------===// // Test Attributes Constraints //===----------------------------------------------------------------------===//