wgsl-reader: Add support for nested array accessors

Bug: tint:501
Change-Id: I23f4e73696f48d29b3f9d63997fa1c5004cf4d34
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/41622
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 415688e..708157b 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -3055,6 +3055,17 @@
     return true;
   }
 
+  // Handle the case when `]` is expected but the actual token is `]]`.
+  // For example, in `arr1[arr2[0]]`.
+  if (tok == Token::Type::kBracketRight && t.IsAttrRight()) {
+    next();
+    auto source = t.source();
+    source.range.begin.column++;
+    token_queue_.push_front({Token::Type::kBracketRight, source});
+    synchronized_ = true;
+    return true;
+  }
+
   std::stringstream err;
   err << "expected '" << Token::TypeToName(tok) << "'";
   if (!use.empty()) {
diff --git a/src/reader/wgsl/parser_impl_postfix_expression_test.cc b/src/reader/wgsl/parser_impl_postfix_expression_test.cc
index 43ed375..6bf2531 100644
--- a/src/reader/wgsl/parser_impl_postfix_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_postfix_expression_test.cc
@@ -217,6 +217,37 @@
   ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
 }
 
+TEST_F(ParserImplTest, PostfixExpression_Array_NestedArrayAccessor) {
+  auto p = parser("a[b[c]]");
+  auto e = p->postfix_expression();
+  EXPECT_TRUE(e.matched);
+  EXPECT_FALSE(e.errored);
+  EXPECT_FALSE(p->has_error()) << p->error();
+  ASSERT_NE(e.value, nullptr);
+
+  const auto* outer_accessor = e->As<ast::ArrayAccessorExpression>();
+  ASSERT_TRUE(outer_accessor);
+
+  const auto* outer_array =
+      outer_accessor->array()->As<ast::IdentifierExpression>();
+  ASSERT_TRUE(outer_array);
+  EXPECT_EQ(outer_array->symbol(), p->builder().Symbols().Get("a"));
+
+  const auto* inner_accessor =
+      outer_accessor->idx_expr()->As<ast::ArrayAccessorExpression>();
+  ASSERT_TRUE(inner_accessor);
+
+  const auto* inner_array =
+      inner_accessor->array()->As<ast::IdentifierExpression>();
+  ASSERT_TRUE(inner_array);
+  EXPECT_EQ(inner_array->symbol(), p->builder().Symbols().Get("b"));
+
+  const auto* index_expr =
+      inner_accessor->idx_expr()->As<ast::IdentifierExpression>();
+  ASSERT_TRUE(index_expr);
+  EXPECT_EQ(index_expr->symbol(), p->builder().Symbols().Get("c"));
+}
+
 }  // namespace
 }  // namespace wgsl
 }  // namespace reader