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:
dan sinclair 2023-02-23 18:34:08 +00:00 committed by Dawn LUCI CQ
parent 20a82acf6a
commit 869bcabf88
10 changed files with 174 additions and 226 deletions

View File

@ -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;
} }

View File

@ -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;
^^ ^^
)"); )");

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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