reader/wgsl: Parse '&' and '*'

Bug: tint:727
Change-Id: I1a2c93017b934fd0884570412f5ed25bf15991bb
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/50820
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ben Clayton 2021-05-13 16:56:32 +00:00 committed by Commit Bot service account
parent 2ef8033212
commit 09587e1d86
2 changed files with 80 additions and 18 deletions

View File

@ -2315,28 +2315,34 @@ Expect<ast::ExpressionList> ParserImpl::expect_argument_expression_list(
// : singular_expression
// | MINUS unary_expression
// | BANG unary_expression
// | STAR unary_expression
// | AND unary_expression
Maybe<ast::Expression*> ParserImpl::unary_expression() {
auto t = peek();
auto source = t.source();
if (t.IsMinus() || t.IsBang()) {
auto name = t.to_name();
next(); // Consume the peek
auto op = ast::UnaryOp::kNegation;
if (t.IsBang())
op = ast::UnaryOp::kNot;
auto expr = unary_expression();
if (expr.errored)
return Failure::kErrored;
if (!expr.matched)
return add_error(peek(),
"unable to parse right side of " + name + " expression");
return create<ast::UnaryOpExpression>(source, op, expr.value);
ast::UnaryOp op;
if (match(Token::Type::kMinus)) {
op = ast::UnaryOp::kNegation;
} else if (match(Token::Type::kBang)) {
op = ast::UnaryOp::kNot;
} else if (match(Token::Type::kStar)) {
op = ast::UnaryOp::kDereference;
} else if (match(Token::Type::kAnd)) {
op = ast::UnaryOp::kAddressOf;
} else {
return singular_expression();
}
return singular_expression();
auto expr = unary_expression();
if (expr.errored) {
return Failure::kErrored;
}
if (!expr.matched) {
return add_error(
peek(), "unable to parse right side of " + t.to_name() + " expression");
}
return create<ast::UnaryOpExpression>(t.source(), op, expr.value);
}
// multiplicative_expr

View File

@ -61,6 +61,62 @@ TEST_F(ParserImplTest, UnaryExpression_Minus) {
EXPECT_EQ(init->literal()->As<ast::SintLiteral>()->value(), 1);
}
TEST_F(ParserImplTest, UnaryExpression_AddressOf) {
auto p = parser("&x");
auto e = p->unary_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
auto* u = e->As<ast::UnaryOpExpression>();
EXPECT_EQ(u->op(), ast::UnaryOp::kAddressOf);
EXPECT_TRUE(u->expr()->Is<ast::IdentifierExpression>());
}
TEST_F(ParserImplTest, UnaryExpression_Dereference) {
auto p = parser("*x");
auto e = p->unary_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
auto* u = e->As<ast::UnaryOpExpression>();
EXPECT_EQ(u->op(), ast::UnaryOp::kDereference);
EXPECT_TRUE(u->expr()->Is<ast::IdentifierExpression>());
}
TEST_F(ParserImplTest, UnaryExpression_AddressOf_Precedence) {
auto p = parser("&x.y");
auto e = p->logical_or_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
auto* u = e->As<ast::UnaryOpExpression>();
EXPECT_EQ(u->op(), ast::UnaryOp::kAddressOf);
EXPECT_TRUE(u->expr()->Is<ast::MemberAccessorExpression>());
}
TEST_F(ParserImplTest, UnaryExpression_Dereference_Precedence) {
auto p = parser("*x.y");
auto e = p->logical_or_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
auto* u = e->As<ast::UnaryOpExpression>();
EXPECT_EQ(u->op(), ast::UnaryOp::kDereference);
EXPECT_TRUE(u->expr()->Is<ast::MemberAccessorExpression>());
}
TEST_F(ParserImplTest, UnaryExpression_Minus_InvalidRHS) {
auto p = parser("-if(a) {}");
auto e = p->unary_expression();