wsgl parser: add expect_lt_gt_block(), use it
Reduces code, paves the way for multiple errors with resynchronization points.
Bug: tint:282
Change-Id: I68018ea8cabe4ec347afa21d1220126d6348d3d1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32280
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 03bdaf4..89c8a35 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -389,17 +389,9 @@
if (dim.matched) {
const char* use = "sampled texture type";
- if (!expect(use, Token::Type::kLessThan))
- return Failure::kErrored;
-
- auto subtype = type_decl();
+ auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); });
if (subtype.errored)
return Failure::kErrored;
- if (!subtype.matched)
- return add_error(peek().source(), "invalid subtype", use);
-
- if (!expect(use, Token::Type::kGreaterThan))
- return Failure::kErrored;
return ctx_.type_mgr().Get(std::make_unique<ast::type::SampledTextureType>(
dim.value, subtype.value));
@@ -409,17 +401,9 @@
if (ms_dim.matched) {
const char* use = "multisampled texture type";
- if (!expect(use, Token::Type::kLessThan))
- return Failure::kErrored;
-
- auto subtype = type_decl();
+ auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); });
if (subtype.errored)
return Failure::kErrored;
- if (!subtype.matched)
- return add_error(peek().source(), "invalid subtype", use);
-
- if (!expect(use, Token::Type::kGreaterThan))
- return Failure::kErrored;
return ctx_.type_mgr().Get(
std::make_unique<ast::type::MultisampledTextureType>(ms_dim.value,
@@ -430,16 +414,12 @@
if (storage.matched) {
const char* use = "storage texture type";
- if (!expect(use, Token::Type::kLessThan))
- return Failure::kErrored;
+ auto format =
+ expect_lt_gt_block(use, [&] { return expect_image_storage_type(use); });
- auto format = expect_image_storage_type(use);
if (format.errored)
return Failure::kErrored;
- if (!expect(use, Token::Type::kGreaterThan))
- return Failure::kErrored;
-
return ctx_.type_mgr().Get(std::make_unique<ast::type::StorageTextureType>(
storage->first, storage->second, format.value));
}
@@ -773,16 +753,14 @@
// variable_storage_decoration
// : LESS_THAN storage_class GREATER_THAN
Maybe<ast::StorageClass> ParserImpl::variable_storage_decoration() {
- if (!match(Token::Type::kLessThan))
+ if (!peek().IsLessThan())
return Failure::kNoMatch;
const char* use = "variable decoration";
- auto sc = expect_storage_class(use);
- if (sc.errored)
- return Failure::kErrored;
+ auto sc = expect_lt_gt_block(use, [&] { return expect_storage_class(use); });
- if (!expect(use, Token::Type::kGreaterThan))
+ if (sc.errored)
return Failure::kErrored;
return sc.value;
@@ -904,30 +882,33 @@
return Failure::kNoMatch;
}
+Expect<ast::type::Type*> ParserImpl::expect_type(const std::string& use) {
+ auto type = type_decl();
+ if (type.errored)
+ return Failure::kErrored;
+ if (!type.matched)
+ return add_error(peek().source(), "invalid type", use);
+ return type.value;
+}
+
Expect<ast::type::Type*> ParserImpl::expect_type_decl_pointer() {
const char* use = "ptr declaration";
- if (!expect(use, Token::Type::kLessThan))
- return Failure::kErrored;
+ return expect_lt_gt_block(use, [&]() -> Expect<ast::type::Type*> {
+ auto sc = expect_storage_class(use);
+ if (sc.errored)
+ return Failure::kErrored;
- auto sc = expect_storage_class(use);
- if (sc.errored)
- return Failure::kErrored;
+ if (!expect(use, Token::Type::kComma))
+ return Failure::kErrored;
- if (!expect(use, Token::Type::kComma))
- return Failure::kErrored;
+ auto subtype = expect_type(use);
+ if (subtype.errored)
+ return Failure::kErrored;
- auto subtype = type_decl();
- if (subtype.errored)
- return Failure::kErrored;
- if (!subtype.matched)
- return add_error(peek().source(), "missing type", use);
-
- if (!expect(use, Token::Type::kGreaterThan))
- return Failure::kErrored;
-
- return ctx_.type_mgr().Get(
- std::make_unique<ast::type::PointerType>(subtype.value, sc.value));
+ return ctx_.type_mgr().Get(
+ std::make_unique<ast::type::PointerType>(subtype.value, sc.value));
+ });
}
Expect<ast::type::Type*> ParserImpl::expect_type_decl_vector(Token t) {
@@ -939,17 +920,9 @@
const char* use = "vector";
- if (!expect(use, Token::Type::kLessThan))
- return Failure::kErrored;
-
- auto subtype = type_decl();
+ auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); });
if (subtype.errored)
return Failure::kErrored;
- if (!subtype.matched)
- return add_error(peek().source(), "unable to determine subtype", use);
-
- if (!expect(use, Token::Type::kGreaterThan))
- return Failure::kErrored;
return ctx_.type_mgr().Get(
std::make_unique<ast::type::VectorType>(subtype.value, count));
@@ -959,29 +932,23 @@
ast::ArrayDecorationList decos) {
const char* use = "array declaration";
- if (!expect(use, Token::Type::kLessThan))
- return Failure::kErrored;
-
- auto subtype = type_decl();
- if (subtype.errored)
- return Failure::kErrored;
- if (!subtype.matched)
- return add_error(peek(), "invalid type for array declaration");
-
- uint32_t size = 0;
- if (match(Token::Type::kComma)) {
- auto val = expect_nonzero_positive_sint("array size");
- if (val.errored)
+ return expect_lt_gt_block(use, [&]() -> Expect<ast::type::Type*> {
+ auto subtype = expect_type(use);
+ if (subtype.errored)
return Failure::kErrored;
- size = val.value;
- }
- if (!expect(use, Token::Type::kGreaterThan))
- return Failure::kErrored;
+ uint32_t size = 0;
+ if (match(Token::Type::kComma)) {
+ auto val = expect_nonzero_positive_sint("array size");
+ if (val.errored)
+ return Failure::kErrored;
+ size = val.value;
+ }
- auto ty = std::make_unique<ast::type::ArrayType>(subtype.value, size);
- ty->set_decorations(std::move(decos));
- return ctx_.type_mgr().Get(std::move(ty));
+ auto ty = std::make_unique<ast::type::ArrayType>(subtype.value, size);
+ ty->set_decorations(std::move(decos));
+ return ctx_.type_mgr().Get(std::move(ty));
+ });
}
Expect<ast::type::Type*> ParserImpl::expect_type_decl_matrix(Token t) {
@@ -1000,17 +967,9 @@
const char* use = "matrix";
- if (!expect(use, Token::Type::kLessThan))
- return Failure::kErrored;
-
- auto subtype = type_decl();
+ auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); });
if (subtype.errored)
return Failure::kErrored;
- if (!subtype.matched)
- return add_error(peek().source(), "unable to determine subtype", use);
-
- if (!expect(use, Token::Type::kGreaterThan))
- return Failure::kErrored;
return ctx_.type_mgr().Get(
std::make_unique<ast::type::MatrixType>(subtype.value, rows, columns));
@@ -1948,17 +1907,9 @@
if (match(Token::Type::kBitcast)) {
const char* use = "bitcast expression";
- if (!expect(use, Token::Type::kLessThan))
- return Failure::kErrored;
-
- auto type = type_decl();
+ auto type = expect_lt_gt_block(use, [&] { return expect_type(use); });
if (type.errored)
return Failure::kErrored;
- if (!type.matched)
- return add_error(peek().source(), "missing type", use);
-
- if (!expect(use, Token::Type::kGreaterThan))
- return Failure::kErrored;
auto params = expect_paren_rhs_stmt();
if (params.errored)
@@ -2927,6 +2878,12 @@
std::forward<F>(body));
}
+template <typename F, typename T>
+T ParserImpl::expect_lt_gt_block(const std::string& use, F&& body) {
+ return expect_block(Token::Type::kLessThan, Token::Type::kGreaterThan, use,
+ std::forward<F>(body));
+}
+
} // namespace wgsl
} // namespace reader
} // namespace tint
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 0dcaa37..b63d1eb 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -645,7 +645,7 @@
/// @param end the token that ends the lexical block
/// @param use a description of what was being parsed if an error was raised
/// @param body a function or lambda that is called to parse the lexical block
- /// body, with the signature: `Expect<Result>()`.
+ /// body, with the signature: `Expect<Result>()` or `Maybe<Result>()`.
/// @return the value returned by |body| if no errors are raised, otherwise
/// an Expect with error state.
template <typename F, typename T = ReturnType<F>>
@@ -658,7 +658,7 @@
/// and |end| arguments, respectively.
/// @param use a description of what was being parsed if an error was raised
/// @param body a function or lambda that is called to parse the lexical block
- /// body, with the signature: `Expect<Result>()`.
+ /// body, with the signature: `Expect<Result>()` or `Maybe<Result>()`.
/// @return the value returned by |body| if no errors are raised, otherwise
/// an Expect with error state.
template <typename F, typename T = ReturnType<F>>
@@ -668,11 +668,21 @@
/// and |end| arguments, respectively.
/// @param use a description of what was being parsed if an error was raised
/// @param body a function or lambda that is called to parse the lexical block
- /// body, with the signature: `Expect<Result>()`.
+ /// body, with the signature: `Expect<Result>()` or `Maybe<Result>()`.
/// @return the value returned by |body| if no errors are raised, otherwise
/// an Expect with error state.
template <typename F, typename T = ReturnType<F>>
T expect_brace_block(const std::string& use, F&& body);
+ /// A convenience function that calls |expect_block| passing
+ /// |Token::Type::kLessThan| and |Token::Type::kGreaterThan| for the |start|
+ /// and |end| arguments, respectively.
+ /// @param use a description of what was being parsed if an error was raised
+ /// @param body a function or lambda that is called to parse the lexical block
+ /// body, with the signature: `Expect<Result>()` or `Maybe<Result>()`.
+ /// @return the value returned by |body| if no errors are raised, otherwise
+ /// an Expect with error state.
+ template <typename F, typename T = ReturnType<F>>
+ T expect_lt_gt_block(const std::string& use, F&& body);
/// Downcasts all the decorations in |list| to the type |T|, raising a parser
/// error if any of the decorations aren't of the type |T|.
@@ -692,6 +702,8 @@
Expect<std::unique_ptr<ast::ConstructorExpression>>
expect_const_expr_internal(uint32_t depth);
+ Expect<ast::type::Type*> expect_type(const std::string& use);
+
Maybe<std::unique_ptr<ast::Statement>> for_header_initializer();
Maybe<std::unique_ptr<ast::Statement>> for_header_continuing();
diff --git a/src/reader/wgsl/parser_impl_error_msg_test.cc b/src/reader/wgsl/parser_impl_error_msg_test.cc
index 08d84eb..9f6bffe 100644
--- a/src/reader/wgsl/parser_impl_error_msg_test.cc
+++ b/src/reader/wgsl/parser_impl_error_msg_test.cc
@@ -105,7 +105,7 @@
TEST_F(ParserImplErrorTest, BitcastExprMissingType) {
EXPECT("fn f() -> void { x = bitcast<>(y); }",
- "test.wgsl:1:30 error: missing type for bitcast expression\n"
+ "test.wgsl:1:30 error: invalid type for bitcast expression\n"
"fn f() -> void { x = bitcast<>(y); }\n"
" ^\n");
}
@@ -548,7 +548,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclSampledTextureInvalidSubtype_Old) {
EXPECT("var x : texture_sampled_1d<1>;",
- "test.wgsl:1:28 error: invalid subtype for sampled texture type\n"
+ "test.wgsl:1:28 error: invalid type for sampled texture type\n"
"var x : texture_sampled_1d<1>;\n"
" ^\n");
}
@@ -569,7 +569,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclSampledTextureInvalidSubtype) {
EXPECT("var x : texture_1d<1>;",
- "test.wgsl:1:20 error: invalid subtype for sampled texture type\n"
+ "test.wgsl:1:20 error: invalid type for sampled texture type\n"
"var x : texture_1d<1>;\n"
" ^\n");
}
@@ -590,7 +590,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclMultisampledTextureInvalidSubtype) {
EXPECT("var x : texture_multisampled_2d<1>;",
- "test.wgsl:1:33 error: invalid subtype for multisampled texture type\n"
+ "test.wgsl:1:33 error: invalid type for multisampled texture type\n"
"var x : texture_multisampled_2d<1>;\n"
" ^\n");
}
@@ -1009,7 +1009,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingType) {
EXPECT("var i : mat4x4<1>;",
- "test.wgsl:1:16 error: unable to determine subtype for matrix\n"
+ "test.wgsl:1:16 error: invalid type for matrix\n"
"var i : mat4x4<1>;\n"
" ^\n");
}
@@ -1051,7 +1051,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingType) {
EXPECT("var i : ptr<in, 1>;",
- "test.wgsl:1:17 error: missing type for ptr declaration\n"
+ "test.wgsl:1:17 error: invalid type for ptr declaration\n"
"var i : ptr<in, 1>;\n"
" ^\n");
}
@@ -1086,7 +1086,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingType) {
EXPECT("var i : vec3<1>;",
- "test.wgsl:1:14 error: unable to determine subtype for vector\n"
+ "test.wgsl:1:14 error: invalid type for vector\n"
"var i : vec3<1>;\n"
" ^\n");
}
diff --git a/src/reader/wgsl/parser_impl_primary_expression_test.cc b/src/reader/wgsl/parser_impl_primary_expression_test.cc
index 249105e..ab77de9 100644
--- a/src/reader/wgsl/parser_impl_primary_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_primary_expression_test.cc
@@ -103,7 +103,7 @@
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:6: unable to determine subtype for vector");
+ EXPECT_EQ(p->error(), "1:6: invalid type for vector");
}
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_MissingLeftParen) {
@@ -245,7 +245,7 @@
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:9: missing type for bitcast expression");
+ EXPECT_EQ(p->error(), "1:9: invalid type for bitcast expression");
}
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_InvalidType) {
diff --git a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
index 2913771..bfc4474 100644
--- a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
+++ b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
@@ -123,7 +123,7 @@
EXPECT_EQ(t.value, nullptr);
EXPECT_FALSE(t.matched);
EXPECT_TRUE(t.errored);
- EXPECT_EQ(p->error(), "1:20: invalid subtype for sampled texture type");
+ EXPECT_EQ(p->error(), "1:20: invalid type for sampled texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan_Old) {
@@ -203,7 +203,7 @@
EXPECT_EQ(t.value, nullptr);
EXPECT_FALSE(t.matched);
EXPECT_TRUE(t.errored);
- EXPECT_EQ(p->error(), "1:12: invalid subtype for sampled texture type");
+ EXPECT_EQ(p->error(), "1:12: invalid type for sampled texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan) {
@@ -256,7 +256,7 @@
EXPECT_EQ(t.value, nullptr);
EXPECT_FALSE(t.matched);
EXPECT_TRUE(t.errored);
- EXPECT_EQ(p->error(), "1:25: invalid subtype for multisampled texture type");
+ EXPECT_EQ(p->error(), "1:25: invalid type for multisampled texture type");
}
TEST_F(ParserImplTest,
diff --git a/src/reader/wgsl/parser_impl_type_decl_test.cc b/src/reader/wgsl/parser_impl_type_decl_test.cc
index a3d6eae..587b09d 100644
--- a/src/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_type_decl_test.cc
@@ -221,7 +221,7 @@
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:6: unable to determine subtype for vector");
+ ASSERT_EQ(p->error(), "1:6: invalid type for vector");
}
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
VecMissingType,
@@ -318,7 +318,7 @@
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:14: missing type for ptr declaration");
+ ASSERT_EQ(p->error(), "1:14: invalid type for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_BadStorageClass) {
@@ -718,7 +718,7 @@
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:8: unable to determine subtype for matrix");
+ ASSERT_EQ(p->error(), "1:8: invalid type for matrix");
}
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
MatrixMissingType,