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>
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 9aba063..663cf47 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -2315,28 +2315,34 @@
// : 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
diff --git a/src/reader/wgsl/parser_impl_unary_expression_test.cc b/src/reader/wgsl/parser_impl_unary_expression_test.cc
index c971a1d..047060d 100644
--- a/src/reader/wgsl/parser_impl_unary_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_unary_expression_test.cc
@@ -61,6 +61,62 @@
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();