From 6835c8df3e016f4607659bfeaae840483fb1cb24 Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Mon, 1 Aug 2022 21:42:54 +0000 Subject: [PATCH] tint/reader: Parse arrays with no type / size Bug: tint:1628 Change-Id: Ieb3c07e7dae6fd1e5acf4dd4819312092e5b5bf5 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97586 Reviewed-by: David Neto Reviewed-by: Antonio Maiorano Commit-Queue: Ben Clayton Kokoro: Kokoro --- src/tint/reader/wgsl/parser_impl.cc | 35 +++++++++++-------- .../reader/wgsl/parser_impl_error_msg_test.cc | 13 ++----- .../reader/wgsl/parser_impl_type_decl_test.cc | 26 ++++++++------ 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc index 3adab59cc1..59f4facafe 100644 --- a/src/tint/reader/wgsl/parser_impl.cc +++ b/src/tint/reader/wgsl/parser_impl.cc @@ -1175,33 +1175,40 @@ Expect ParserImpl::expect_type_decl_vector(const Token& t) { Expect ParserImpl::expect_type_decl_array(const Token& t) { const char* use = "array declaration"; - const ast::Expression* size = nullptr; + struct TypeAndSize { + const ast::Type* type = nullptr; + const ast::Expression* size = nullptr; + }; - auto subtype = expect_lt_gt_block(use, [&]() -> Expect { + if (!peek_is(Token::Type::kLessThan)) { + return builder_.ty.array(make_source_range_from(t.source()), nullptr, nullptr); + } + + auto type_size = expect_lt_gt_block(use, [&]() -> Expect { auto type = expect_type(use); if (type.errored) { return Failure::kErrored; } - if (match(Token::Type::kComma)) { - auto expr = primary_expression(); - if (expr.errored) { - return Failure::kErrored; - } else if (!expr.matched) { - return add_error(peek(), "expected array size expression"); - } - - size = std::move(expr.value); + if (!match(Token::Type::kComma)) { + return TypeAndSize{type.value, nullptr}; } - return type.value; + auto size = primary_expression(); + if (size.errored) { + return Failure::kErrored; + } else if (!size.matched) { + return add_error(peek(), "expected array size expression"); + } + + return TypeAndSize{type.value, size.value}; }); - if (subtype.errored) { + if (type_size.errored) { return Failure::kErrored; } - return builder_.ty.array(make_source_range_from(t.source()), subtype.value, size); + return builder_.ty.array(make_source_range_from(t.source()), type_size->type, type_size->size); } Expect ParserImpl::expect_type_decl_matrix(const Token& t) { diff --git a/src/tint/reader/wgsl/parser_impl_error_msg_test.cc b/src/tint/reader/wgsl/parser_impl_error_msg_test.cc index 6a825de3f7..81613b429f 100644 --- a/src/tint/reader/wgsl/parser_impl_error_msg_test.cc +++ b/src/tint/reader/wgsl/parser_impl_error_msg_test.cc @@ -603,8 +603,9 @@ let i : vec2 = vec2(1., 2.; } TEST_F(ParserImplErrorTest, GlobalDeclLetBadConstLiteral) { - EXPECT("let i : vec2 = vec2(!);", - R"(test.wgsl:1:1 warning: use of deprecated language feature: module-scope 'let' has been replaced with 'const' + EXPECT( + "let i : vec2 = vec2(!);", + R"(test.wgsl:1:1 warning: use of deprecated language feature: module-scope 'let' has been replaced with 'const' let i : vec2 = vec2(!); ^^^ @@ -821,14 +822,6 @@ type meow = f32 )"); } -TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingLessThan) { - EXPECT("var i : array;", - R"(test.wgsl:1:14 error: expected '<' for array declaration -var i : array; - ^ -)"); -} - TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingGreaterThan) { EXPECT("var i : array' for array declaration diff --git a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc index 5459af67bf..880f87ae4c 100644 --- a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc +++ b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc @@ -501,6 +501,22 @@ TEST_F(ParserImplTest, TypeDecl_Array_Runtime_Vec) { EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 17u}})); } +TEST_F(ParserImplTest, TypeDecl_Array_InferTypeAndSize) { + auto p = parser("array"); + auto t = p->type_decl(); + EXPECT_TRUE(t.matched); + EXPECT_FALSE(t.errored); + ASSERT_NE(t.value, nullptr) << p->error(); + ASSERT_FALSE(p->has_error()); + ASSERT_TRUE(t.value->Is()); + + auto* a = t.value->As(); + EXPECT_FALSE(a->IsRuntimeArray()); + EXPECT_EQ(a->type, nullptr); + EXPECT_EQ(a->count, nullptr); + EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 6u}})); +} + TEST_F(ParserImplTest, TypeDecl_Array_BadSize) { auto p = parser("array"); auto t = p->type_decl(); @@ -521,16 +537,6 @@ TEST_F(ParserImplTest, TypeDecl_Array_MissingSize) { ASSERT_EQ(p->error(), "1:11: expected array size expression"); } -TEST_F(ParserImplTest, TypeDecl_Array_MissingLessThan) { - auto p = parser("array f32>"); - auto t = p->type_decl(); - EXPECT_TRUE(t.errored); - EXPECT_FALSE(t.matched); - ASSERT_EQ(t.value, nullptr); - ASSERT_TRUE(p->has_error()); - ASSERT_EQ(p->error(), "1:7: expected '<' for array declaration"); -} - TEST_F(ParserImplTest, TypeDecl_Array_MissingGreaterThan) { auto p = parser("arraytype_decl();