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>
This commit is contained in:
Ben Clayton 2020-11-11 14:10:25 +00:00 committed by Commit Bot service account
parent a4f49d91dc
commit 00bc8ba88c
6 changed files with 81 additions and 112 deletions

View File

@ -389,17 +389,9 @@ Maybe<ast::type::Type*> ParserImpl::texture_sampler_types() {
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 @@ Maybe<ast::type::Type*> ParserImpl::texture_sampler_types() {
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 @@ Maybe<ast::type::Type*> ParserImpl::texture_sampler_types() {
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 @@ Expect<ParserImpl::TypedIdentifier> ParserImpl::expect_variable_ident_decl(
// 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 @@ Maybe<ast::type::Type*> ParserImpl::type_decl() {
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 @@ Expect<ast::type::Type*> ParserImpl::expect_type_decl_vector(Token t) {
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 @@ Expect<ast::type::Type*> ParserImpl::expect_type_decl_array(
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 @@ Expect<ast::type::Type*> ParserImpl::expect_type_decl_matrix(Token t) {
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 @@ Maybe<std::unique_ptr<ast::Expression>> ParserImpl::primary_expression() {
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 @@ T ParserImpl::expect_brace_block(const std::string& use, F&& body) {
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

View File

@ -645,7 +645,7 @@ class ParserImpl {
/// @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 @@ class ParserImpl {
/// 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 @@ class ParserImpl {
/// 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 @@ class ParserImpl {
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();

View File

@ -105,7 +105,7 @@ TEST_F(ParserImplErrorTest, BitcastExprMissingGreaterThan) {
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, GlobalDeclSampledTextureMissingGreaterThan_Old) {
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, GlobalDeclSampledTextureMissingGreaterThan) {
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, GlobalDeclMultisampledTextureMissingGreaterThan) {
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, GlobalDeclVarMatrixMissingGreaterThan) {
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, GlobalDeclVarPtrMissingStorageClass) {
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, GlobalDeclVarVectorMissingGreaterThan) {
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");
}

View File

@ -103,7 +103,7 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
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 @@ TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingType) {
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) {

View File

@ -123,7 +123,7 @@ TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType_Old) {
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 @@ TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType) {
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 @@ TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_MissingType) {
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,

View File

@ -221,7 +221,7 @@ TEST_P(VecMissingType, Handles_Missing_Type) {
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 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_MissingType) {
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 @@ TEST_P(MatrixMissingType, Handles_Missing_Type) {
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,