reader/wgsl: Allow constants without initializers

This is valid when they are overridable constants. The resolver will
validate whether or not this is the case.

Change-Id: Ic6659c58e5046117f64794efec3300b0245a5e91
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/50043
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index c595892..9cfe32e 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -496,7 +496,9 @@
 }
 
 // global_constant_decl
-//  : variable_decoration_list* CONST variable_ident_decl EQUAL const_expr
+//  : attribute_list* LET variable_ident_decl global_const_initializer?
+// global_const_initializer
+//  : EQUAL const_expr
 Maybe<ast::Variable*> ParserImpl::global_constant_decl(
     ast::DecorationList& decos) {
   if (!match(Token::Type::kLet)) {
@@ -515,12 +517,13 @@
   if (decl.errored)
     return Failure::kErrored;
 
-  if (!expect(use, Token::Type::kEqual))
-    return Failure::kErrored;
-
-  auto init = expect_const_expr();
-  if (init.errored)
-    return Failure::kErrored;
+  ast::ConstructorExpression* initializer = nullptr;
+  if (match(Token::Type::kEqual)) {
+    auto init = expect_const_expr();
+    if (init.errored)
+      return Failure::kErrored;
+    initializer = std::move(init.value);
+  }
 
   return create<ast::Variable>(
       decl->source,                             // source
@@ -528,7 +531,7 @@
       ast::StorageClass::kNone,                 // storage_class
       decl->type,                               // type
       true,                                     // is_const
-      init.value,                               // constructor
+      initializer,                              // constructor
       std::move(decos));                        // decorations
 }
 
diff --git a/src/reader/wgsl/parser_impl_error_msg_test.cc b/src/reader/wgsl/parser_impl_error_msg_test.cc
index bca27f3..b56f6fe 100644
--- a/src/reader/wgsl/parser_impl_error_msg_test.cc
+++ b/src/reader/wgsl/parser_impl_error_msg_test.cc
@@ -508,13 +508,6 @@
          "                                    ^\n");
 }
 
-TEST_F(ParserImplErrorTest, GlobalDeclConstMissingAssignment) {
-  EXPECT("let i : vec2<i32>;",
-         "test.wgsl:1:18 error: expected '=' for let declaration\n"
-         "let i : vec2<i32>;\n"
-         "                 ^\n");
-}
-
 TEST_F(ParserImplErrorTest, GlobalDeclConstBadConstLiteral) {
   EXPECT("let i : vec2<i32> = vec2<i32>(!);",
          "test.wgsl:1:31 error: unable to parse constant literal\n"
diff --git a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
index f0f6720..5f27155 100644
--- a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
@@ -48,19 +48,6 @@
       ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations()));
 }
 
-TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) {
-  auto p = parser("let a : f32 1.");
-  auto decos = p->decoration_list();
-  EXPECT_FALSE(decos.errored);
-  EXPECT_FALSE(decos.matched);
-  auto e = p->global_constant_decl(decos.value);
-  EXPECT_TRUE(p->has_error());
-  EXPECT_TRUE(e.errored);
-  EXPECT_FALSE(e.matched);
-  EXPECT_EQ(e.value, nullptr);
-  EXPECT_EQ(p->error(), "1:13: expected '=' for let declaration");
-}
-
 TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
   auto p = parser("let a : invalid = 1.");
   auto decos = p->decoration_list();
diff --git a/src/reader/wgsl/parser_impl_global_decl_test.cc b/src/reader/wgsl/parser_impl_global_decl_test.cc
index dcecf15..79e81a3 100644
--- a/src/reader/wgsl/parser_impl_global_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_decl_test.cc
@@ -64,10 +64,10 @@
 }
 
 TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_Invalid) {
-  auto p = parser("let a : vec2<i32>;");
+  auto p = parser("let a : vec2<i32> 1.0;");
   p->expect_global_decl();
   ASSERT_TRUE(p->has_error());
-  EXPECT_EQ(p->error(), "1:18: expected '=' for let declaration");
+  EXPECT_EQ(p->error(), "1:19: expected ';' for let declaration");
 }
 
 TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_MissingSemicolon) {