mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-08 15:43:41 +00:00
Make attribute grammar generic.
This Cl updates the parser to use a generic attribute grammar. Bug: tint:1845 Change-Id: Icd600a2d87f03972f60d89b27fe0eef7be7667d5 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121100 Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
20a82acf6a
commit
869bcabf88
@ -2984,85 +2984,12 @@ Expect<const ast::Attribute*> ParserImpl::expect_attribute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// attribute
|
// attribute
|
||||||
// : ATTR 'align' PAREN_LEFT expression COMMA? PAREN_RIGHT
|
// : ATTR identifier ( PAREN_LEFT expression ( COMMA expression )? COMMA? PAREN_RIGHT )?
|
||||||
// | ATTR 'binding' PAREN_LEFT expression COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'builtin' PAREN_LEFT builtin_value_name COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'const'
|
|
||||||
// | ATTR 'diagnostic' diagnostic_control
|
|
||||||
// | ATTR 'group' PAREN_LEFT expression COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'id' PAREN_LEFT expression COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'interpolate' PAREN_LEFT interpolation_type_name COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'interpolate' PAREN_LEFT interpolation_type_name COMMA
|
|
||||||
// interpolation_sample_name COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'invariant'
|
|
||||||
// | ATTR 'location' PAREN_LEFT expression COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'must_use'
|
|
||||||
// | ATTR 'size' PAREN_LEFT expression COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'workgroup_size' PAREN_LEFT expression COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'workgroup_size' PAREN_LEFT expression COMMA expression COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'workgroup_size' PAREN_LEFT expression COMMA expression COMMA
|
|
||||||
// expression COMMA? PAREN_RIGHT
|
|
||||||
// | ATTR 'vertex'
|
|
||||||
// | ATTR 'fragment'
|
|
||||||
// | ATTR 'compute'
|
|
||||||
Maybe<const ast::Attribute*> ParserImpl::attribute() {
|
Maybe<const ast::Attribute*> ParserImpl::attribute() {
|
||||||
using Result = Maybe<const ast::Attribute*>;
|
// Note, the ATTR is matched by the called `attribute_list` in this case, so it is not matched
|
||||||
|
// here and this has to be an attribute.
|
||||||
auto& t = next();
|
auto& t = next();
|
||||||
|
|
||||||
if (!t.IsIdentifier() && !(t.Is(Token::Type::kDiagnostic))) {
|
|
||||||
return Failure::kNoMatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t == "align") {
|
|
||||||
const char* use = "align attribute";
|
|
||||||
return expect_paren_block(use, [&]() -> Result {
|
|
||||||
auto expr = expression();
|
|
||||||
if (expr.errored) {
|
|
||||||
return Failure::kErrored;
|
|
||||||
}
|
|
||||||
if (!expr.matched) {
|
|
||||||
return add_error(peek(), "expected align expression");
|
|
||||||
}
|
|
||||||
match(Token::Type::kComma);
|
|
||||||
|
|
||||||
return create<ast::StructMemberAlignAttribute>(t.source(), expr.value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t == "binding") {
|
|
||||||
const char* use = "binding attribute";
|
|
||||||
return expect_paren_block(use, [&]() -> Result {
|
|
||||||
auto expr = expression();
|
|
||||||
if (expr.errored) {
|
|
||||||
return Failure::kErrored;
|
|
||||||
}
|
|
||||||
if (!expr.matched) {
|
|
||||||
return add_error(peek(), "expected binding expression");
|
|
||||||
}
|
|
||||||
match(Token::Type::kComma);
|
|
||||||
|
|
||||||
return create<ast::BindingAttribute>(t.source(), expr.value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t == "builtin") {
|
|
||||||
return expect_paren_block("builtin attribute", [&]() -> Result {
|
|
||||||
auto builtin = expect_expression("builtin name");
|
|
||||||
if (builtin.errored) {
|
|
||||||
return Failure::kErrored;
|
|
||||||
}
|
|
||||||
match(Token::Type::kComma);
|
|
||||||
|
|
||||||
return create<ast::BuiltinAttribute>(t.source(), builtin.value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t == "compute") {
|
|
||||||
return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kCompute);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note, `const` is not valid in a WGSL source file, it's internal only
|
|
||||||
|
|
||||||
if (t.Is(Token::Type::kDiagnostic)) {
|
if (t.Is(Token::Type::kDiagnostic)) {
|
||||||
auto control = expect_diagnostic_control();
|
auto control = expect_diagnostic_control();
|
||||||
if (control.errored) {
|
if (control.errored) {
|
||||||
@ -3071,152 +2998,173 @@ Maybe<const ast::Attribute*> ParserImpl::attribute() {
|
|||||||
return create<ast::DiagnosticAttribute>(t.source(), std::move(control.value));
|
return create<ast::DiagnosticAttribute>(t.source(), std::move(control.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!t.IsIdentifier()) {
|
||||||
|
return Failure::kNoMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::Vector<const ast::Expression*, 2> exprs;
|
||||||
|
auto parse = [&](uint32_t min, uint32_t max) -> Maybe<bool> {
|
||||||
|
// Handle no parameter items which should have no parens
|
||||||
|
if (min == 0) {
|
||||||
|
auto& p = peek();
|
||||||
|
if (p.Is(Token::Type::kParenLeft)) {
|
||||||
|
return add_error(p.source(), t.to_str() + " attribute doesn't take parenthesis");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = expect_paren_block(t.to_str() + " attribute", [&]() -> Expect<bool> {
|
||||||
|
while (continue_parsing()) {
|
||||||
|
if (peek().Is(Token::Type::kParenRight)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto expr = expect_expression(t.to_str());
|
||||||
|
if (expr.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
exprs.Push(expr.value);
|
||||||
|
|
||||||
|
if (!match(Token::Type::kComma)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (res.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exprs.IsEmpty() || exprs.Length() < min) {
|
||||||
|
return add_error(t.source(),
|
||||||
|
t.to_str() + " expects" + (min != max ? " at least " : " ") +
|
||||||
|
std::to_string(min) + " argument" + (min > 1 ? "s" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exprs.Length() > max) {
|
||||||
|
return add_error(t.source(),
|
||||||
|
t.to_str() + " expects" + (min != max ? " at most " : " ") +
|
||||||
|
std::to_string(max) + " argument" + (max > 1 ? "s" : "") +
|
||||||
|
", got " + std::to_string(exprs.Length()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (t == "align") {
|
||||||
|
auto res = parse(1, 1);
|
||||||
|
if (res.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
return create<ast::StructMemberAlignAttribute>(t.source(), exprs[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == "binding") {
|
||||||
|
auto res = parse(1, 1);
|
||||||
|
if (res.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
return create<ast::BindingAttribute>(t.source(), exprs[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == "builtin") {
|
||||||
|
auto res = parse(1, 1);
|
||||||
|
if (res.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
return create<ast::BuiltinAttribute>(t.source(), exprs[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t == "compute") {
|
||||||
|
auto res = parse(0, 0);
|
||||||
|
if (res.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kCompute);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, `const` is not valid in a WGSL source file, it's internal only
|
||||||
|
|
||||||
if (t == "fragment") {
|
if (t == "fragment") {
|
||||||
|
auto res = parse(0, 0);
|
||||||
|
if (res.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kFragment);
|
return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kFragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == "group") {
|
if (t == "group") {
|
||||||
const char* use = "group attribute";
|
auto res = parse(1, 1);
|
||||||
return expect_paren_block(use, [&]() -> Result {
|
if (res.errored) {
|
||||||
auto expr = expression();
|
|
||||||
if (expr.errored) {
|
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
if (!expr.matched) {
|
return create<ast::GroupAttribute>(t.source(), exprs[0]);
|
||||||
return add_error(peek(), "expected group expression");
|
|
||||||
}
|
|
||||||
match(Token::Type::kComma);
|
|
||||||
|
|
||||||
return create<ast::GroupAttribute>(t.source(), expr.value);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == "id") {
|
if (t == "id") {
|
||||||
const char* use = "id attribute";
|
auto res = parse(1, 1);
|
||||||
return expect_paren_block(use, [&]() -> Result {
|
if (res.errored) {
|
||||||
auto expr = expression();
|
|
||||||
if (expr.errored) {
|
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
if (!expr.matched) {
|
return create<ast::IdAttribute>(t.source(), exprs[0]);
|
||||||
return add_error(peek(), "expected id expression");
|
|
||||||
}
|
|
||||||
match(Token::Type::kComma);
|
|
||||||
|
|
||||||
return create<ast::IdAttribute>(t.source(), expr.value);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == "interpolate") {
|
if (t == "interpolate") {
|
||||||
return expect_paren_block("interpolate attribute", [&]() -> Result {
|
auto res = parse(1, 2);
|
||||||
auto type = expect_expression("interpolation type");
|
if (res.errored) {
|
||||||
if (type.errored) {
|
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
return create<ast::InterpolateAttribute>(t.source(), exprs[0],
|
||||||
const ast::Expression* sampling = nullptr;
|
exprs.Length() == 2 ? exprs[1] : nullptr);
|
||||||
if (match(Token::Type::kComma)) {
|
|
||||||
if (!peek_is(Token::Type::kParenRight)) {
|
|
||||||
auto sample = expect_expression("interpolation sampling");
|
|
||||||
if (sample.errored) {
|
|
||||||
return Failure::kErrored;
|
|
||||||
}
|
|
||||||
|
|
||||||
sampling = sample.value;
|
|
||||||
match(Token::Type::kComma);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return create<ast::InterpolateAttribute>(t.source(), type.value, sampling);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == "invariant") {
|
if (t == "invariant") {
|
||||||
|
auto res = parse(0, 0);
|
||||||
|
if (res.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
return create<ast::InvariantAttribute>(t.source());
|
return create<ast::InvariantAttribute>(t.source());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == "location") {
|
if (t == "location") {
|
||||||
const char* use = "location attribute";
|
auto res = parse(1, 1);
|
||||||
return expect_paren_block(use, [&]() -> Result {
|
if (res.errored) {
|
||||||
auto expr = expression();
|
|
||||||
if (expr.errored) {
|
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
if (!expr.matched) {
|
return builder_.Location(t.source(), exprs[0]);
|
||||||
return add_error(peek(), "expected location expression");
|
|
||||||
}
|
|
||||||
match(Token::Type::kComma);
|
|
||||||
|
|
||||||
return builder_.Location(t.source(), expr.value);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == "must_use") {
|
if (t == "must_use") {
|
||||||
|
auto res = parse(0, 0);
|
||||||
|
if (res.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
return create<ast::MustUseAttribute>(t.source());
|
return create<ast::MustUseAttribute>(t.source());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == "size") {
|
if (t == "size") {
|
||||||
const char* use = "size attribute";
|
auto res = parse(1, 1);
|
||||||
return expect_paren_block(use, [&]() -> Result {
|
if (res.errored) {
|
||||||
auto expr = expression();
|
|
||||||
if (expr.errored) {
|
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
if (!expr.matched) {
|
return builder_.MemberSize(t.source(), exprs[0]);
|
||||||
return add_error(peek(), "expected size expression");
|
|
||||||
}
|
|
||||||
match(Token::Type::kComma);
|
|
||||||
|
|
||||||
return builder_.MemberSize(t.source(), expr.value);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == "vertex") {
|
if (t == "vertex") {
|
||||||
|
auto res = parse(0, 0);
|
||||||
|
if (res.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kVertex);
|
return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kVertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t == "workgroup_size") {
|
if (t == "workgroup_size") {
|
||||||
return expect_paren_block("workgroup_size attribute", [&]() -> Result {
|
auto res = parse(1, 3);
|
||||||
const ast::Expression* x = nullptr;
|
if (res.errored) {
|
||||||
const ast::Expression* y = nullptr;
|
|
||||||
const ast::Expression* z = nullptr;
|
|
||||||
|
|
||||||
auto expr = expression();
|
|
||||||
if (expr.errored) {
|
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
} else if (!expr.matched) {
|
|
||||||
return add_error(peek(), "expected workgroup_size x parameter");
|
|
||||||
}
|
}
|
||||||
x = std::move(expr.value);
|
return create<ast::WorkgroupAttribute>(t.source(), exprs[0],
|
||||||
|
exprs.Length() > 1 ? exprs[1] : nullptr,
|
||||||
if (match(Token::Type::kComma)) {
|
exprs.Length() > 2 ? exprs[2] : nullptr);
|
||||||
if (!peek_is(Token::Type::kParenRight)) {
|
|
||||||
expr = expression();
|
|
||||||
if (expr.errored) {
|
|
||||||
return Failure::kErrored;
|
|
||||||
} else if (!expr.matched) {
|
|
||||||
return add_error(peek(), "expected workgroup_size y parameter");
|
|
||||||
}
|
|
||||||
y = std::move(expr.value);
|
|
||||||
|
|
||||||
if (match(Token::Type::kComma)) {
|
|
||||||
if (!peek_is(Token::Type::kParenRight)) {
|
|
||||||
expr = expression();
|
|
||||||
if (expr.errored) {
|
|
||||||
return Failure::kErrored;
|
|
||||||
} else if (!expr.matched) {
|
|
||||||
return add_error(peek(), "expected workgroup_size z parameter");
|
|
||||||
}
|
|
||||||
z = std::move(expr.value);
|
|
||||||
|
|
||||||
match(Token::Type::kComma);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return create<ast::WorkgroupAttribute>(t.source(), x, y, z);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return Failure::kNoMatch;
|
return Failure::kNoMatch;
|
||||||
}
|
}
|
||||||
|
@ -353,15 +353,15 @@ fn f() { const_assert true }
|
|||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeXInvalid) {
|
TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeXInvalid) {
|
||||||
EXPECT("@workgroup_size() fn f() {}",
|
EXPECT("@workgroup_size() fn f() {}",
|
||||||
R"(test.wgsl:1:17 error: expected workgroup_size x parameter
|
R"(test.wgsl:1:2 error: workgroup_size expects at least 1 argument
|
||||||
@workgroup_size() fn f() {}
|
@workgroup_size() fn f() {}
|
||||||
^
|
^^^^^^^^^^^^^^
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeYInvalid) {
|
TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeYInvalid) {
|
||||||
EXPECT("@workgroup_size(1, fn) fn f() {}",
|
EXPECT("@workgroup_size(1, fn) fn f() {}",
|
||||||
R"(test.wgsl:1:20 error: expected workgroup_size y parameter
|
R"(test.wgsl:1:20 error: expected expression for workgroup_size
|
||||||
@workgroup_size(1, fn) fn f() {}
|
@workgroup_size(1, fn) fn f() {}
|
||||||
^^
|
^^
|
||||||
)");
|
)");
|
||||||
@ -369,7 +369,7 @@ TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeYInvalid) {
|
|||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeZInvalid) {
|
TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeZInvalid) {
|
||||||
EXPECT("@workgroup_size(1, 2, fn) fn f() {}",
|
EXPECT("@workgroup_size(1, 2, fn) fn f() {}",
|
||||||
R"(test.wgsl:1:23 error: expected workgroup_size z parameter
|
R"(test.wgsl:1:23 error: expected expression for workgroup_size
|
||||||
@workgroup_size(1, 2, fn) fn f() {}
|
@workgroup_size(1, 2, fn) fn f() {}
|
||||||
^^
|
^^
|
||||||
)");
|
)");
|
||||||
@ -672,7 +672,7 @@ struct S { 1 : i32, };
|
|||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclStructMemberAlignInvaldValue) {
|
TEST_F(ParserImplErrorTest, GlobalDeclStructMemberAlignInvaldValue) {
|
||||||
EXPECT("struct S { @align(fn) i : i32, };",
|
EXPECT("struct S { @align(fn) i : i32, };",
|
||||||
R"(test.wgsl:1:19 error: expected align expression
|
R"(test.wgsl:1:19 error: expected expression for align
|
||||||
struct S { @align(fn) i : i32, };
|
struct S { @align(fn) i : i32, };
|
||||||
^^
|
^^
|
||||||
)");
|
)");
|
||||||
@ -680,7 +680,7 @@ struct S { @align(fn) i : i32, };
|
|||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclStructMemberSizeInvaldValue) {
|
TEST_F(ParserImplErrorTest, GlobalDeclStructMemberSizeInvaldValue) {
|
||||||
EXPECT("struct S { @size(if) i : i32, };",
|
EXPECT("struct S { @size(if) i : i32, };",
|
||||||
R"(test.wgsl:1:18 error: expected size expression
|
R"(test.wgsl:1:18 error: expected expression for size
|
||||||
struct S { @size(if) i : i32, };
|
struct S { @size(if) i : i32, };
|
||||||
^^
|
^^
|
||||||
)");
|
)");
|
||||||
@ -761,7 +761,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarAttrLocationMissingRParen) {
|
|||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrLocationInvalidValue) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrLocationInvalidValue) {
|
||||||
EXPECT("@location(if) var i : i32;",
|
EXPECT("@location(if) var i : i32;",
|
||||||
R"(test.wgsl:1:11 error: expected location expression
|
R"(test.wgsl:1:11 error: expected expression for location
|
||||||
@location(if) var i : i32;
|
@location(if) var i : i32;
|
||||||
^^
|
^^
|
||||||
)");
|
)");
|
||||||
@ -785,7 +785,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarAttrIdMissingRParen) {
|
|||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrIdInvalidValue) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrIdInvalidValue) {
|
||||||
EXPECT("@id(if) var i : i32;",
|
EXPECT("@id(if) var i : i32;",
|
||||||
R"(test.wgsl:1:5 error: expected id expression
|
R"(test.wgsl:1:5 error: expected expression for id
|
||||||
@id(if) var i : i32;
|
@id(if) var i : i32;
|
||||||
^^
|
^^
|
||||||
)");
|
)");
|
||||||
@ -825,7 +825,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBindingMissingRParen) {
|
|||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBindingInvalidValue) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBindingInvalidValue) {
|
||||||
EXPECT("@binding(if) var i : i32;",
|
EXPECT("@binding(if) var i : i32;",
|
||||||
R"(test.wgsl:1:10 error: expected binding expression
|
R"(test.wgsl:1:10 error: expected expression for binding
|
||||||
@binding(if) var i : i32;
|
@binding(if) var i : i32;
|
||||||
^^
|
^^
|
||||||
)");
|
)");
|
||||||
@ -849,7 +849,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarAttrGroupMissingRParen) {
|
|||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBindingGroupValue) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBindingGroupValue) {
|
||||||
EXPECT("@group(if) var i : i32;",
|
EXPECT("@group(if) var i : i32;",
|
||||||
R"(test.wgsl:1:8 error: expected group expression
|
R"(test.wgsl:1:8 error: expected expression for group
|
||||||
@group(if) var i : i32;
|
@group(if) var i : i32;
|
||||||
^^
|
^^
|
||||||
)");
|
)");
|
||||||
|
@ -100,7 +100,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_1Param_TrailingComma_Double) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:18: expected workgroup_size y parameter");
|
EXPECT_EQ(p->error(), "1:18: expected expression for workgroup_size");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Workgroup_2Param) {
|
TEST_F(ParserImplTest, Attribute_Workgroup_2Param) {
|
||||||
@ -195,7 +195,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup21Param_TrailingComma_Double) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:20: expected workgroup_size z parameter");
|
EXPECT_EQ(p->error(), "1:20: expected expression for workgroup_size");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Workgroup_3Param) {
|
TEST_F(ParserImplTest, Attribute_Workgroup_3Param) {
|
||||||
@ -323,7 +323,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_TooManyValues) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:25: expected ')' for workgroup_size attribute");
|
EXPECT_EQ(p->error(), "1:1: workgroup_size expects at most 3 arguments, got 4");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Workgroup_MissingLeftParam) {
|
TEST_F(ParserImplTest, Attribute_Workgroup_MissingLeftParam) {
|
||||||
@ -353,7 +353,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_MissingValues) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:16: expected workgroup_size x parameter");
|
EXPECT_EQ(p->error(), "1:1: workgroup_size expects at least 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Workgroup_Missing_X_Value) {
|
TEST_F(ParserImplTest, Attribute_Workgroup_Missing_X_Value) {
|
||||||
@ -363,7 +363,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_Missing_X_Value) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:16: expected workgroup_size x parameter");
|
EXPECT_EQ(p->error(), "1:16: expected expression for workgroup_size");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Workgroup_Missing_Y_Comma) {
|
TEST_F(ParserImplTest, Attribute_Workgroup_Missing_Y_Comma) {
|
||||||
@ -383,7 +383,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_Missing_Y_Value) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:19: expected workgroup_size y parameter");
|
EXPECT_EQ(p->error(), "1:19: expected expression for workgroup_size");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Workgroup_Missing_Z_Comma) {
|
TEST_F(ParserImplTest, Attribute_Workgroup_Missing_Z_Comma) {
|
||||||
|
@ -138,7 +138,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_InvalidAttribute) {
|
|||||||
EXPECT_NE(e.value, nullptr);
|
EXPECT_NE(e.value, nullptr);
|
||||||
|
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:10: expected binding expression");
|
EXPECT_EQ(p->error(), "1:2: binding expects 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidConstExpr) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidConstExpr) {
|
||||||
|
@ -46,7 +46,7 @@ TEST_F(ParserImplTest, AttributeDecl_MissingValue) {
|
|||||||
EXPECT_TRUE(attrs.errored);
|
EXPECT_TRUE(attrs.errored);
|
||||||
EXPECT_FALSE(attrs.matched);
|
EXPECT_FALSE(attrs.matched);
|
||||||
EXPECT_TRUE(attrs.value.IsEmpty());
|
EXPECT_TRUE(attrs.value.IsEmpty());
|
||||||
EXPECT_EQ(p->error(), "1:11: expected location expression");
|
EXPECT_EQ(p->error(), "1:2: location expects 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, AttributeDecl_MissingParenRight) {
|
TEST_F(ParserImplTest, AttributeDecl_MissingParenRight) {
|
||||||
|
@ -66,7 +66,7 @@ TEST_F(ParserImplTest, StructBodyDecl_InvalidAlign) {
|
|||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(m.errored);
|
ASSERT_TRUE(m.errored);
|
||||||
EXPECT_EQ(p->error(), "3:10: expected align expression");
|
EXPECT_EQ(p->error(), "3:10: expected expression for align");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructBodyDecl_InvalidSize) {
|
TEST_F(ParserImplTest, StructBodyDecl_InvalidSize) {
|
||||||
@ -77,7 +77,7 @@ TEST_F(ParserImplTest, StructBodyDecl_InvalidSize) {
|
|||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(m.errored);
|
ASSERT_TRUE(m.errored);
|
||||||
EXPECT_EQ(p->error(), "3:9: expected size expression");
|
EXPECT_EQ(p->error(), "3:9: expected expression for size");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, StructBodyDecl_MissingClosingBracket) {
|
TEST_F(ParserImplTest, StructBodyDecl_MissingClosingBracket) {
|
||||||
|
@ -44,7 +44,7 @@ TEST_F(ParserImplTest, AttributeDecl_InvalidAttribute) {
|
|||||||
EXPECT_TRUE(p->has_error()) << p->error();
|
EXPECT_TRUE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(attrs.errored);
|
EXPECT_TRUE(attrs.errored);
|
||||||
EXPECT_FALSE(attrs.matched);
|
EXPECT_FALSE(attrs.matched);
|
||||||
EXPECT_EQ(p->error(), "1:7: expected size expression");
|
EXPECT_EQ(p->error(), "1:7: expected expression for size");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -104,7 +104,7 @@ TEST_F(ParserImplTest, Attribute_Size_MissingValue) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:6: expected size expression");
|
EXPECT_EQ(p->error(), "1:1: size expects 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Size_MissingInvalid) {
|
TEST_F(ParserImplTest, Attribute_Size_MissingInvalid) {
|
||||||
@ -114,7 +114,7 @@ TEST_F(ParserImplTest, Attribute_Size_MissingInvalid) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:6: expected size expression");
|
EXPECT_EQ(p->error(), "1:6: expected expression for size");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Align) {
|
TEST_F(ParserImplTest, Attribute_Align) {
|
||||||
@ -209,7 +209,7 @@ TEST_F(ParserImplTest, Attribute_Align_MissingValue) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:7: expected align expression");
|
EXPECT_EQ(p->error(), "1:1: align expects 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Align_ExpressionInvalid) {
|
TEST_F(ParserImplTest, Attribute_Align_ExpressionInvalid) {
|
||||||
|
@ -115,7 +115,7 @@ TEST_F(ParserImplTest, StructMember_InvalidAttribute) {
|
|||||||
ASSERT_EQ(m.value, nullptr);
|
ASSERT_EQ(m.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:7: expected size expression");
|
EXPECT_EQ(p->error(), "1:7: expected expression for size");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -105,7 +105,7 @@ TEST_F(ParserImplTest, Attribute_Id_MissingValue) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:4: expected id expression");
|
EXPECT_EQ(p->error(), "1:1: id expects 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Id_MissingInvalid) {
|
TEST_F(ParserImplTest, Attribute_Id_MissingInvalid) {
|
||||||
@ -115,7 +115,7 @@ TEST_F(ParserImplTest, Attribute_Id_MissingInvalid) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:4: expected id expression");
|
EXPECT_EQ(p->error(), "1:4: expected expression for id");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Location) {
|
TEST_F(ParserImplTest, Attribute_Location) {
|
||||||
@ -204,7 +204,7 @@ TEST_F(ParserImplTest, Attribute_Location_MissingValue) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:10: expected location expression");
|
EXPECT_EQ(p->error(), "1:1: location expects 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Location_MissingInvalid) {
|
TEST_F(ParserImplTest, Attribute_Location_MissingInvalid) {
|
||||||
@ -214,7 +214,7 @@ TEST_F(ParserImplTest, Attribute_Location_MissingInvalid) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:10: expected location expression");
|
EXPECT_EQ(p->error(), "1:10: expected expression for location");
|
||||||
}
|
}
|
||||||
|
|
||||||
class BuiltinTest : public ParserImplTestWithParam<builtin::BuiltinValue> {};
|
class BuiltinTest : public ParserImplTestWithParam<builtin::BuiltinValue> {};
|
||||||
@ -293,7 +293,7 @@ TEST_F(ParserImplTest, Attribute_Builtin_MissingValue) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), R"(1:9: expected expression for builtin name)");
|
EXPECT_EQ(p->error(), "1:1: builtin expects 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Interpolate_Flat) {
|
TEST_F(ParserImplTest, Attribute_Interpolate_Flat) {
|
||||||
@ -335,7 +335,7 @@ TEST_F(ParserImplTest, Attribute_Interpolate_Single_DoubleTrailingComma) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), R"(1:18: expected expression for interpolation sampling)");
|
EXPECT_EQ(p->error(), "1:18: expected expression for interpolate");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Interpolate_Perspective_Center) {
|
TEST_F(ParserImplTest, Attribute_Interpolate_Perspective_Center) {
|
||||||
@ -429,7 +429,7 @@ TEST_F(ParserImplTest, Attribute_Interpolate_MissingFirstValue) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), R"(1:13: expected expression for interpolation type)");
|
EXPECT_EQ(p->error(), "1:1: interpolate expects at least 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Binding) {
|
TEST_F(ParserImplTest, Attribute_Binding) {
|
||||||
@ -520,7 +520,7 @@ TEST_F(ParserImplTest, Attribute_Binding_MissingValue) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: expected binding expression");
|
EXPECT_EQ(p->error(), "1:1: binding expects 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Binding_MissingInvalid) {
|
TEST_F(ParserImplTest, Attribute_Binding_MissingInvalid) {
|
||||||
@ -530,7 +530,7 @@ TEST_F(ParserImplTest, Attribute_Binding_MissingInvalid) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:9: expected binding expression");
|
EXPECT_EQ(p->error(), "1:9: expected expression for binding");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_group) {
|
TEST_F(ParserImplTest, Attribute_group) {
|
||||||
@ -621,7 +621,7 @@ TEST_F(ParserImplTest, Attribute_Group_MissingValue) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:7: expected group expression");
|
EXPECT_EQ(p->error(), "1:1: group expects 1 argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Attribute_Group_MissingInvalid) {
|
TEST_F(ParserImplTest, Attribute_Group_MissingInvalid) {
|
||||||
@ -631,7 +631,7 @@ TEST_F(ParserImplTest, Attribute_Group_MissingInvalid) {
|
|||||||
EXPECT_TRUE(attr.errored);
|
EXPECT_TRUE(attr.errored);
|
||||||
EXPECT_EQ(attr.value, nullptr);
|
EXPECT_EQ(attr.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:7: expected group expression");
|
EXPECT_EQ(p->error(), "1:7: expected expression for group");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
Loading…
x
Reference in New Issue
Block a user