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
|
||||
// : ATTR 'align' PAREN_LEFT 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'
|
||||
// : ATTR identifier ( PAREN_LEFT expression ( COMMA expression )? COMMA? PAREN_RIGHT )?
|
||||
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();
|
||||
|
||||
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)) {
|
||||
auto control = expect_diagnostic_control();
|
||||
if (control.errored) {
|
||||
|
@ -3071,152 +2998,173 @@ Maybe<const ast::Attribute*> ParserImpl::attribute() {
|
|||
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") {
|
||||
auto res = parse(0, 0);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kFragment);
|
||||
}
|
||||
|
||||
if (t == "group") {
|
||||
const char* use = "group attribute";
|
||||
return expect_paren_block(use, [&]() -> Result {
|
||||
auto expr = expression();
|
||||
if (expr.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!expr.matched) {
|
||||
return add_error(peek(), "expected group expression");
|
||||
}
|
||||
match(Token::Type::kComma);
|
||||
|
||||
return create<ast::GroupAttribute>(t.source(), expr.value);
|
||||
});
|
||||
auto res = parse(1, 1);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return create<ast::GroupAttribute>(t.source(), exprs[0]);
|
||||
}
|
||||
|
||||
if (t == "id") {
|
||||
const char* use = "id attribute";
|
||||
return expect_paren_block(use, [&]() -> Result {
|
||||
auto expr = expression();
|
||||
if (expr.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!expr.matched) {
|
||||
return add_error(peek(), "expected id expression");
|
||||
}
|
||||
match(Token::Type::kComma);
|
||||
|
||||
return create<ast::IdAttribute>(t.source(), expr.value);
|
||||
});
|
||||
auto res = parse(1, 1);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return create<ast::IdAttribute>(t.source(), exprs[0]);
|
||||
}
|
||||
|
||||
if (t == "interpolate") {
|
||||
return expect_paren_block("interpolate attribute", [&]() -> Result {
|
||||
auto type = expect_expression("interpolation type");
|
||||
if (type.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
const ast::Expression* sampling = 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);
|
||||
});
|
||||
auto res = parse(1, 2);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return create<ast::InterpolateAttribute>(t.source(), exprs[0],
|
||||
exprs.Length() == 2 ? exprs[1] : nullptr);
|
||||
}
|
||||
|
||||
if (t == "invariant") {
|
||||
auto res = parse(0, 0);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return create<ast::InvariantAttribute>(t.source());
|
||||
}
|
||||
|
||||
if (t == "location") {
|
||||
const char* use = "location attribute";
|
||||
return expect_paren_block(use, [&]() -> Result {
|
||||
auto expr = expression();
|
||||
if (expr.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!expr.matched) {
|
||||
return add_error(peek(), "expected location expression");
|
||||
}
|
||||
match(Token::Type::kComma);
|
||||
|
||||
return builder_.Location(t.source(), expr.value);
|
||||
});
|
||||
auto res = parse(1, 1);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return builder_.Location(t.source(), exprs[0]);
|
||||
}
|
||||
|
||||
if (t == "must_use") {
|
||||
auto res = parse(0, 0);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return create<ast::MustUseAttribute>(t.source());
|
||||
}
|
||||
|
||||
if (t == "size") {
|
||||
const char* use = "size attribute";
|
||||
return expect_paren_block(use, [&]() -> Result {
|
||||
auto expr = expression();
|
||||
if (expr.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!expr.matched) {
|
||||
return add_error(peek(), "expected size expression");
|
||||
}
|
||||
match(Token::Type::kComma);
|
||||
|
||||
return builder_.MemberSize(t.source(), expr.value);
|
||||
});
|
||||
auto res = parse(1, 1);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return builder_.MemberSize(t.source(), exprs[0]);
|
||||
}
|
||||
|
||||
if (t == "vertex") {
|
||||
auto res = parse(0, 0);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kVertex);
|
||||
}
|
||||
|
||||
if (t == "workgroup_size") {
|
||||
return expect_paren_block("workgroup_size attribute", [&]() -> Result {
|
||||
const ast::Expression* x = nullptr;
|
||||
const ast::Expression* y = nullptr;
|
||||
const ast::Expression* z = nullptr;
|
||||
|
||||
auto expr = expression();
|
||||
if (expr.errored) {
|
||||
return Failure::kErrored;
|
||||
} else if (!expr.matched) {
|
||||
return add_error(peek(), "expected workgroup_size x parameter");
|
||||
}
|
||||
x = 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 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);
|
||||
});
|
||||
auto res = parse(1, 3);
|
||||
if (res.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return create<ast::WorkgroupAttribute>(t.source(), exprs[0],
|
||||
exprs.Length() > 1 ? exprs[1] : nullptr,
|
||||
exprs.Length() > 2 ? exprs[2] : nullptr);
|
||||
}
|
||||
return Failure::kNoMatch;
|
||||
}
|
||||
|
|
|
@ -353,15 +353,15 @@ fn f() { const_assert true }
|
|||
|
||||
TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeXInvalid) {
|
||||
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() {}
|
||||
^
|
||||
^^^^^^^^^^^^^^
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeYInvalid) {
|
||||
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() {}
|
||||
^^
|
||||
)");
|
||||
|
@ -369,7 +369,7 @@ TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeYInvalid) {
|
|||
|
||||
TEST_F(ParserImplErrorTest, FunctionDeclWorkgroupSizeZInvalid) {
|
||||
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() {}
|
||||
^^
|
||||
)");
|
||||
|
@ -672,7 +672,7 @@ struct S { 1 : i32, };
|
|||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclStructMemberAlignInvaldValue) {
|
||||
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, };
|
||||
^^
|
||||
)");
|
||||
|
@ -680,7 +680,7 @@ struct S { @align(fn) i : i32, };
|
|||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclStructMemberSizeInvaldValue) {
|
||||
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, };
|
||||
^^
|
||||
)");
|
||||
|
@ -761,7 +761,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarAttrLocationMissingRParen) {
|
|||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrLocationInvalidValue) {
|
||||
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;
|
||||
^^
|
||||
)");
|
||||
|
@ -785,7 +785,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarAttrIdMissingRParen) {
|
|||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrIdInvalidValue) {
|
||||
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;
|
||||
^^
|
||||
)");
|
||||
|
@ -825,7 +825,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBindingMissingRParen) {
|
|||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBindingInvalidValue) {
|
||||
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;
|
||||
^^
|
||||
)");
|
||||
|
@ -849,7 +849,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarAttrGroupMissingRParen) {
|
|||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclVarAttrBindingGroupValue) {
|
||||
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;
|
||||
^^
|
||||
)");
|
||||
|
|
|
@ -100,7 +100,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_1Param_TrailingComma_Double) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -195,7 +195,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup21Param_TrailingComma_Double) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -323,7 +323,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_TooManyValues) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -353,7 +353,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_MissingValues) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -363,7 +363,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_Missing_X_Value) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -383,7 +383,7 @@ TEST_F(ParserImplTest, Attribute_Workgroup_Missing_Y_Value) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
|
|
@ -138,7 +138,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_InvalidAttribute) {
|
|||
EXPECT_NE(e.value, nullptr);
|
||||
|
||||
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) {
|
||||
|
|
|
@ -46,7 +46,7 @@ TEST_F(ParserImplTest, AttributeDecl_MissingValue) {
|
|||
EXPECT_TRUE(attrs.errored);
|
||||
EXPECT_FALSE(attrs.matched);
|
||||
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) {
|
||||
|
|
|
@ -66,7 +66,7 @@ TEST_F(ParserImplTest, StructBodyDecl_InvalidAlign) {
|
|||
auto m = p->expect_struct_body_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
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) {
|
||||
|
@ -77,7 +77,7 @@ TEST_F(ParserImplTest, StructBodyDecl_InvalidSize) {
|
|||
auto m = p->expect_struct_body_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
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) {
|
||||
|
|
|
@ -44,7 +44,7 @@ TEST_F(ParserImplTest, AttributeDecl_InvalidAttribute) {
|
|||
EXPECT_TRUE(p->has_error()) << p->error();
|
||||
EXPECT_TRUE(attrs.errored);
|
||||
EXPECT_FALSE(attrs.matched);
|
||||
EXPECT_EQ(p->error(), "1:7: expected size expression");
|
||||
EXPECT_EQ(p->error(), "1:7: expected expression for size");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -104,7 +104,7 @@ TEST_F(ParserImplTest, Attribute_Size_MissingValue) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -114,7 +114,7 @@ TEST_F(ParserImplTest, Attribute_Size_MissingInvalid) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -209,7 +209,7 @@ TEST_F(ParserImplTest, Attribute_Align_MissingValue) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
|
|
@ -115,7 +115,7 @@ TEST_F(ParserImplTest, StructMember_InvalidAttribute) {
|
|||
ASSERT_EQ(m.value, nullptr);
|
||||
|
||||
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
|
||||
|
|
|
@ -105,7 +105,7 @@ TEST_F(ParserImplTest, Attribute_Id_MissingValue) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -115,7 +115,7 @@ TEST_F(ParserImplTest, Attribute_Id_MissingInvalid) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -204,7 +204,7 @@ TEST_F(ParserImplTest, Attribute_Location_MissingValue) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -214,7 +214,7 @@ TEST_F(ParserImplTest, Attribute_Location_MissingInvalid) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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> {};
|
||||
|
@ -293,7 +293,7 @@ TEST_F(ParserImplTest, Attribute_Builtin_MissingValue) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -335,7 +335,7 @@ TEST_F(ParserImplTest, Attribute_Interpolate_Single_DoubleTrailingComma) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -429,7 +429,7 @@ TEST_F(ParserImplTest, Attribute_Interpolate_MissingFirstValue) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -520,7 +520,7 @@ TEST_F(ParserImplTest, Attribute_Binding_MissingValue) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -530,7 +530,7 @@ TEST_F(ParserImplTest, Attribute_Binding_MissingInvalid) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -621,7 +621,7 @@ TEST_F(ParserImplTest, Attribute_Group_MissingValue) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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) {
|
||||
|
@ -631,7 +631,7 @@ TEST_F(ParserImplTest, Attribute_Group_MissingInvalid) {
|
|||
EXPECT_TRUE(attr.errored);
|
||||
EXPECT_EQ(attr.value, nullptr);
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue