Update WGSL grammar builtins to match spec.

This CL removes the builtin_decoration from the parser in favour of
using IDENT tokens for builtins. We still convert to an enum in the
parser and validate the value provided.

Bug: tint:41
Change-Id: If5dc3844e3325c75951e7b320c123cf66cb8e106
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/22300
Reviewed-by: David Neto <dneto@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 93bc286..698068f 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -732,7 +732,6 @@
     "src/reader/wgsl/parser_impl_assignment_stmt_test.cc",
     "src/reader/wgsl/parser_impl_body_stmt_test.cc",
     "src/reader/wgsl/parser_impl_break_stmt_test.cc",
-    "src/reader/wgsl/parser_impl_builtin_decoration_test.cc",
     "src/reader/wgsl/parser_impl_case_body_test.cc",
     "src/reader/wgsl/parser_impl_const_expr_test.cc",
     "src/reader/wgsl/parser_impl_const_literal_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a1637eb..22fdd35 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -363,7 +363,6 @@
     reader/wgsl/parser_impl_assignment_stmt_test.cc
     reader/wgsl/parser_impl_body_stmt_test.cc
     reader/wgsl/parser_impl_break_stmt_test.cc
-    reader/wgsl/parser_impl_builtin_decoration_test.cc
     reader/wgsl/parser_impl_case_body_test.cc
     reader/wgsl/parser_impl_const_expr_test.cc
     reader/wgsl/parser_impl_const_literal_test.cc
diff --git a/src/reader/wgsl/lexer.cc b/src/reader/wgsl/lexer.cc
index 4c8545e..5d11237 100644
--- a/src/reader/wgsl/lexer.cc
+++ b/src/reader/wgsl/lexer.cc
@@ -524,20 +524,12 @@
     return {Token::Type::kFine, source, "fine"};
   if (str == "fn")
     return {Token::Type::kFn, source, "fn"};
-  if (str == "frag_coord")
-    return {Token::Type::kFragCoord, source, "frag_coord"};
-  if (str == "frag_depth")
-    return {Token::Type::kFragDepth, source, "frag_depth"};
   if (str == "fragment")
     return {Token::Type::kFragment, source, "fragment"};
-  if (str == "front_facing")
-    return {Token::Type::kFrontFacing, source, "front_facing"};
   if (str == "function")
     return {Token::Type::kFunction, source, "function"};
   if (str == "fwidth")
     return {Token::Type::kFwidth, source, "fwidth"};
-  if (str == "global_invocation_id")
-    return {Token::Type::kGlobalInvocationId, source, "global_invocation_id"};
   if (str == "i32")
     return {Token::Type::kI32, source, "i32"};
   if (str == "if")
@@ -548,8 +540,6 @@
     return {Token::Type::kImport, source, "import"};
   if (str == "in")
     return {Token::Type::kIn, source, "in"};
-  if (str == "instance_idx")
-    return {Token::Type::kInstanceIdx, source, "instance_idx"};
   if (str == "is_nan")
     return {Token::Type::kIsNan, source, "is_nan"};
   if (str == "is_inf")
@@ -560,10 +550,6 @@
     return {Token::Type::kIsNormal, source, "is_normal"};
   if (str == "kill")
     return {Token::Type::kKill, source, "kill"};
-  if (str == "local_invocation_id")
-    return {Token::Type::kLocalInvocationId, source, "local_invocation_id"};
-  if (str == "local_invocation_idx")
-    return {Token::Type::kLocalInvocationIdx, source, "local_invocation_idx"};
   if (str == "location")
     return {Token::Type::kLocation, source, "location"};
   if (str == "loop")
@@ -586,16 +572,12 @@
     return {Token::Type::kMat4x3, source, "mat4x3"};
   if (str == "mat4x4")
     return {Token::Type::kMat4x4, source, "mat4x4"};
-  if (str == "num_workgroups")
-    return {Token::Type::kNumWorkgroups, source, "num_workgroups"};
   if (str == "offset")
     return {Token::Type::kOffset, source, "offset"};
   if (str == "out")
     return {Token::Type::kOut, source, "out"};
   if (str == "outer_product")
     return {Token::Type::kOuterProduct, source, "outer_product"};
-  if (str == "position")
-    return {Token::Type::kPosition, source, "position"};
   if (str == "private")
     return {Token::Type::kPrivate, source, "private"};
   if (str == "ptr")
@@ -632,14 +614,10 @@
     return {Token::Type::kVec4, source, "vec4"};
   if (str == "vertex")
     return {Token::Type::kVertex, source, "vertex"};
-  if (str == "vertex_idx")
-    return {Token::Type::kVertexIdx, source, "vertex_idx"};
   if (str == "void")
     return {Token::Type::kVoid, source, "void"};
   if (str == "workgroup")
     return {Token::Type::kWorkgroup, source, "workgroup"};
-  if (str == "workgroup_size")
-    return {Token::Type::kWorkgroupSize, source, "workgroup_size"};
 
   return {};
 }
diff --git a/src/reader/wgsl/lexer_test.cc b/src/reader/wgsl/lexer_test.cc
index 9944ee0..0b514f9 100644
--- a/src/reader/wgsl/lexer_test.cc
+++ b/src/reader/wgsl/lexer_test.cc
@@ -437,26 +437,19 @@
         TokenData{"false", Token::Type::kFalse},
         TokenData{"fine", Token::Type::kFine},
         TokenData{"fn", Token::Type::kFn},
-        TokenData{"frag_coord", Token::Type::kFragCoord},
-        TokenData{"frag_depth", Token::Type::kFragDepth},
         TokenData{"fragment", Token::Type::kFragment},
-        TokenData{"front_facing", Token::Type::kFrontFacing},
         TokenData{"function", Token::Type::kFunction},
         TokenData{"fwidth", Token::Type::kFwidth},
-        TokenData{"global_invocation_id", Token::Type::kGlobalInvocationId},
         TokenData{"i32", Token::Type::kI32},
         TokenData{"if", Token::Type::kIf},
         TokenData{"image", Token::Type::kImage},
         TokenData{"import", Token::Type::kImport},
         TokenData{"in", Token::Type::kIn},
-        TokenData{"instance_idx", Token::Type::kInstanceIdx},
         TokenData{"is_nan", Token::Type::kIsNan},
         TokenData{"is_inf", Token::Type::kIsInf},
         TokenData{"is_finite", Token::Type::kIsFinite},
         TokenData{"is_normal", Token::Type::kIsNormal},
         TokenData{"kill", Token::Type::kKill},
-        TokenData{"local_invocation_id", Token::Type::kLocalInvocationId},
-        TokenData{"local_invocation_idx", Token::Type::kLocalInvocationIdx},
         TokenData{"location", Token::Type::kLocation},
         TokenData{"loop", Token::Type::kLoop},
         TokenData{"mat2x2", Token::Type::kMat2x2},
@@ -468,11 +461,9 @@
         TokenData{"mat4x2", Token::Type::kMat4x2},
         TokenData{"mat4x3", Token::Type::kMat4x3},
         TokenData{"mat4x4", Token::Type::kMat4x4},
-        TokenData{"num_workgroups", Token::Type::kNumWorkgroups},
         TokenData{"offset", Token::Type::kOffset},
         TokenData{"out", Token::Type::kOut},
         TokenData{"outer_product", Token::Type::kOuterProduct},
-        TokenData{"position", Token::Type::kPosition},
         TokenData{"private", Token::Type::kPrivate},
         TokenData{"ptr", Token::Type::kPtr},
         TokenData{"return", Token::Type::kReturn},
@@ -491,10 +482,8 @@
         TokenData{"vec3", Token::Type::kVec3},
         TokenData{"vec4", Token::Type::kVec4},
         TokenData{"vertex", Token::Type::kVertex},
-        TokenData{"vertex_idx", Token::Type::kVertexIdx},
         TokenData{"void", Token::Type::kVoid},
-        TokenData{"workgroup", Token::Type::kWorkgroup},
-        TokenData{"workgroup_size", Token::Type::kWorkgroupSize}));
+        TokenData{"workgroup", Token::Type::kWorkgroup}));
 
 using KeywordTest_Reserved = testing::TestWithParam<const char*>;
 TEST_P(KeywordTest_Reserved, Parses) {
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index e64a74b..0cfd6e5 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -70,6 +70,46 @@
 namespace tint {
 namespace reader {
 namespace wgsl {
+namespace {
+
+ast::Builtin ident_to_builtin(const std::string& str) {
+  if (str == "position") {
+    return ast::Builtin::kPosition;
+  }
+  if (str == "vertex_idx") {
+    return ast::Builtin::kVertexIdx;
+  }
+  if (str == "instance_idx") {
+    return ast::Builtin::kInstanceIdx;
+  }
+  if (str == "front_facing") {
+    return ast::Builtin::kFrontFacing;
+  }
+  if (str == "frag_coord") {
+    return ast::Builtin::kFragCoord;
+  }
+  if (str == "frag_depth") {
+    return ast::Builtin::kFragDepth;
+  }
+  if (str == "num_workgroups") {
+    return ast::Builtin::kNumWorkgroups;
+  }
+  if (str == "workgroup_size") {
+    return ast::Builtin::kWorkgroupSize;
+  }
+  if (str == "local_invocation_id") {
+    return ast::Builtin::kLocalInvocationId;
+  }
+  if (str == "local_invocation_idx") {
+    return ast::Builtin::kLocalInvocationIdx;
+  }
+  if (str == "global_invocation_id") {
+    return ast::Builtin::kGlobalInvocationId;
+  }
+  return ast::Builtin::kNone;
+}
+
+}  // namespace
 
 ParserImpl::ParserImpl(Context* ctx, const std::string& input)
     : ctx_(*ctx), lexer_(std::make_unique<Lexer>(input)) {}
@@ -395,7 +435,7 @@
 }
 
 // variable_decoration_list
-//  : ATTR_LEFT variable_decoration (COMMA variable_decoration)* ATTR_RIGHT
+//  : ATTR_LEFT (variable_decoration COMMA)* variable_decoration ATTR_RIGHT
 ast::VariableDecorationList ParserImpl::variable_decoration_list() {
   ast::VariableDecorationList decos;
 
@@ -452,7 +492,7 @@
 
 // variable_decoration
 //  : LOCATION INT_LITERAL
-//  | BUILTIN builtin_decoration
+//  | BUILTIN IDENT
 //  | BINDING INT_LITERAL
 //  | SET INT_LITERAL
 std::unique_ptr<ast::VariableDecoration> ParserImpl::variable_decoration() {
@@ -471,11 +511,15 @@
   if (t.IsBuiltin()) {
     next();  // consume the peek
 
-    ast::Builtin builtin = builtin_decoration();
-    if (has_error())
+    t = next();
+    if (!t.IsIdentifier() || t.to_str().empty()) {
+      set_error(t, "expected identifier for builtin");
       return {};
+    }
+
+    ast::Builtin builtin = ident_to_builtin(t.to_str());
     if (builtin == ast::Builtin::kNone) {
-      set_error(peek(), "invalid value for builtin decoration");
+      set_error(t, "invalid value for builtin decoration");
       return {};
     }
 
@@ -507,67 +551,6 @@
   return nullptr;
 }
 
-// builtin_decoration
-//  : POSITION
-//  | VERTEX_IDX
-//  | INSTANCE_IDX
-//  | FRONT_FACING
-//  | FRAG_COORD
-//  | FRAG_DEPTH
-//  | NUM_WORKGROUPS
-//  | WORKGROUP_SIZE
-//  | LOCAL_INVOC_ID
-//  | LOCAL_INVOC_IDX
-//  | GLOBAL_INVOC_ID
-ast::Builtin ParserImpl::builtin_decoration() {
-  auto t = peek();
-  if (t.IsPosition()) {
-    next();  // consume the peek
-    return ast::Builtin::kPosition;
-  }
-  if (t.IsVertexIdx()) {
-    next();  // consume the peek
-    return ast::Builtin::kVertexIdx;
-  }
-  if (t.IsInstanceIdx()) {
-    next();  // consume the peek
-    return ast::Builtin::kInstanceIdx;
-  }
-  if (t.IsFrontFacing()) {
-    next();  // consume the peek
-    return ast::Builtin::kFrontFacing;
-  }
-  if (t.IsFragCoord()) {
-    next();  // consume the peek
-    return ast::Builtin::kFragCoord;
-  }
-  if (t.IsFragDepth()) {
-    next();  // consume the peek
-    return ast::Builtin::kFragDepth;
-  }
-  if (t.IsNumWorkgroups()) {
-    next();  // consume the peek
-    return ast::Builtin::kNumWorkgroups;
-  }
-  if (t.IsWorkgroupSize()) {
-    next();  // consume the peek
-    return ast::Builtin::kWorkgroupSize;
-  }
-  if (t.IsLocalInvocationId()) {
-    next();  // consume the peek
-    return ast::Builtin::kLocalInvocationId;
-  }
-  if (t.IsLocalInvocationIdx()) {
-    next();  // consume the peek
-    return ast::Builtin::kLocalInvocationIdx;
-  }
-  if (t.IsGlobalInvocationId()) {
-    next();  // consume the peek
-    return ast::Builtin::kGlobalInvocationId;
-  }
-  return ast::Builtin::kNone;
-}
-
 // variable_decl
 //   : VAR variable_storage_decoration? variable_ident_decl
 std::unique_ptr<ast::Variable> ParserImpl::variable_decl() {
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 4f33cf0..3767686 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -117,9 +117,6 @@
   /// Parses a `variable_decoration` grammar element
   /// @returns the variable decoration or nullptr if an error is encountered
   std::unique_ptr<ast::VariableDecoration> variable_decoration();
-  /// Parses a `builtin_decoration` grammar element
-  /// @returns the builtin or Builtin::kNone if none matched
-  ast::Builtin builtin_decoration();
   /// Parses a `variable_decl` grammar element
   /// @returns the parsed variable or nullptr otherwise
   std::unique_ptr<ast::Variable> variable_decl();
diff --git a/src/reader/wgsl/parser_impl_builtin_decoration_test.cc b/src/reader/wgsl/parser_impl_builtin_decoration_test.cc
deleted file mode 100644
index db95974..0000000
--- a/src/reader/wgsl/parser_impl_builtin_decoration_test.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2020 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "gtest/gtest.h"
-#include "src/ast/builtin.h"
-#include "src/reader/wgsl/parser_impl.h"
-#include "src/reader/wgsl/parser_impl_test_helper.h"
-
-namespace tint {
-namespace reader {
-namespace wgsl {
-namespace {
-
-struct BuiltinData {
-  const char* input;
-  ast::Builtin result;
-};
-inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
-  out << std::string(data.input);
-  return out;
-}
-
-class BuiltinTest : public testing::TestWithParam<BuiltinData> {
- public:
-  BuiltinTest() = default;
-  ~BuiltinTest() override = default;
-
-  void SetUp() override { ctx_.Reset(); }
-
-  void TearDown() override { impl_ = nullptr; }
-
-  ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
-    return impl_.get();
-  }
-
- private:
-  std::unique_ptr<ParserImpl> impl_;
-  Context ctx_;
-};
-
-TEST_P(BuiltinTest, Parses) {
-  auto params = GetParam();
-  auto* p = parser(params.input);
-
-  auto builtin = p->builtin_decoration();
-  ASSERT_FALSE(p->has_error());
-  EXPECT_EQ(builtin, params.result);
-
-  auto t = p->next();
-  EXPECT_TRUE(t.IsEof());
-}
-INSTANTIATE_TEST_SUITE_P(
-    ParserImplTest,
-    BuiltinTest,
-    testing::Values(
-        BuiltinData{"position", ast::Builtin::kPosition},
-        BuiltinData{"vertex_idx", ast::Builtin::kVertexIdx},
-        BuiltinData{"instance_idx", ast::Builtin::kInstanceIdx},
-        BuiltinData{"front_facing", ast::Builtin::kFrontFacing},
-        BuiltinData{"frag_coord", ast::Builtin::kFragCoord},
-        BuiltinData{"frag_depth", ast::Builtin::kFragDepth},
-        BuiltinData{"num_workgroups", ast::Builtin::kNumWorkgroups},
-        BuiltinData{"workgroup_size", ast::Builtin::kWorkgroupSize},
-        BuiltinData{"local_invocation_id", ast::Builtin::kLocalInvocationId},
-        BuiltinData{"local_invocation_idx", ast::Builtin::kLocalInvocationIdx},
-        BuiltinData{"global_invocation_id",
-                    ast::Builtin::kGlobalInvocationId}));
-
-TEST_F(ParserImplTest, BuiltinDecoration_NoMatch) {
-  auto* p = parser("not-a-builtin");
-  auto builtin = p->builtin_decoration();
-  ASSERT_EQ(builtin, ast::Builtin::kNone);
-
-  auto t = p->next();
-  EXPECT_TRUE(t.IsIdentifier());
-  EXPECT_EQ(t.to_str(), "not");
-}
-
-}  // namespace
-}  // namespace wgsl
-}  // namespace reader
-}  // namespace tint
diff --git a/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc b/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
index a93e21d..85cb1b1 100644
--- a/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
@@ -26,7 +26,7 @@
 TEST_F(ParserImplTest, VariableDecorationList_Parses) {
   auto* p = parser(R"([[location 4, builtin position]])");
   auto decos = p->variable_decoration_list();
-  ASSERT_FALSE(p->has_error());
+  ASSERT_FALSE(p->has_error()) << p->error();
   ASSERT_EQ(decos.size(), 2u);
   ASSERT_TRUE(decos[0]->IsLocation());
   EXPECT_EQ(decos[0]->AsLocation()->value(), 4u);
diff --git a/src/reader/wgsl/parser_impl_variable_decoration_test.cc b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
index 8c30a26..4fc9e5c 100644
--- a/src/reader/wgsl/parser_impl_variable_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
@@ -52,23 +52,77 @@
   EXPECT_EQ(p->error(), "1:10: invalid value for location decoration");
 }
 
-TEST_F(ParserImplTest, VariableDecoration_Builtin) {
-  auto* p = parser("builtin frag_depth");
+struct BuiltinData {
+  const char* input;
+  ast::Builtin result;
+};
+inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
+  out << std::string(data.input);
+  return out;
+}
+class BuiltinTest : public testing::TestWithParam<BuiltinData> {
+ public:
+  BuiltinTest() = default;
+  ~BuiltinTest() override = default;
+
+  void SetUp() override { ctx_.Reset(); }
+
+  void TearDown() override { impl_ = nullptr; }
+
+  ParserImpl* parser(const std::string& str) {
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
+    return impl_.get();
+  }
+
+ private:
+  std::unique_ptr<ParserImpl> impl_;
+  Context ctx_;
+};
+
+TEST_P(BuiltinTest, VariableDecoration_Builtin) {
+  auto params = GetParam();
+  auto* p = parser(std::string("builtin ") + params.input);
+
   auto deco = p->variable_decoration();
-  ASSERT_FALSE(p->has_error());
+  ASSERT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(deco, nullptr);
   ASSERT_TRUE(deco->IsBuiltin());
 
   auto* builtin = deco->AsBuiltin();
-  EXPECT_EQ(builtin->value(), ast::Builtin::kFragDepth);
+  EXPECT_EQ(builtin->value(), params.result);
 }
+INSTANTIATE_TEST_SUITE_P(
+    ParserImplTest,
+    BuiltinTest,
+    testing::Values(
+        BuiltinData{"position", ast::Builtin::kPosition},
+        BuiltinData{"vertex_idx", ast::Builtin::kVertexIdx},
+        BuiltinData{"instance_idx", ast::Builtin::kInstanceIdx},
+        BuiltinData{"front_facing", ast::Builtin::kFrontFacing},
+        BuiltinData{"frag_coord", ast::Builtin::kFragCoord},
+        BuiltinData{"frag_depth", ast::Builtin::kFragDepth},
+        BuiltinData{"num_workgroups", ast::Builtin::kNumWorkgroups},
+        BuiltinData{"workgroup_size", ast::Builtin::kWorkgroupSize},
+        BuiltinData{"local_invocation_id", ast::Builtin::kLocalInvocationId},
+        BuiltinData{"local_invocation_idx", ast::Builtin::kLocalInvocationIdx},
+        BuiltinData{"global_invocation_id",
+                    ast::Builtin::kGlobalInvocationId}));
 
 TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingValue) {
   auto* p = parser("builtin");
   auto deco = p->variable_decoration();
   ASSERT_EQ(deco, nullptr);
   ASSERT_TRUE(p->has_error());
-  EXPECT_EQ(p->error(), "1:8: invalid value for builtin decoration");
+  EXPECT_EQ(p->error(), "1:8: expected identifier for builtin");
+}
+
+
+TEST_F(ParserImplTest, VariableDecoration_Builtin_InvalidValue) {
+  auto* p = parser("builtin other_thingy");
+  auto deco = p->variable_decoration();
+  ASSERT_EQ(deco, nullptr);
+  ASSERT_TRUE(p->has_error());
+  EXPECT_EQ(p->error(), "1:9: invalid value for builtin decoration");
 }
 
 TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingInvalid) {
@@ -76,7 +130,7 @@
   auto deco = p->variable_decoration();
   ASSERT_EQ(deco, nullptr);
   ASSERT_TRUE(p->has_error());
-  EXPECT_EQ(p->error(), "1:9: invalid value for builtin decoration");
+  EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
 }
 
 TEST_F(ParserImplTest, VariableDecoration_Binding) {
diff --git a/src/reader/wgsl/token.cc b/src/reader/wgsl/token.cc
index 0d78a9c..300fbe4 100644
--- a/src/reader/wgsl/token.cc
+++ b/src/reader/wgsl/token.cc
@@ -161,20 +161,12 @@
       return "fine";
     case Token::Type::kFn:
       return "fn";
-    case Token::Type::kFragCoord:
-      return "frag_coord";
-    case Token::Type::kFragDepth:
-      return "frag_depth";
     case Token::Type::kFragment:
       return "fragment";
-    case Token::Type::kFrontFacing:
-      return "front_facing";
     case Token::Type::kFunction:
       return "function";
     case Token::Type::kFwidth:
       return "fwidth";
-    case Token::Type::kGlobalInvocationId:
-      return "global_invocation_id";
     case Token::Type::kI32:
       return "i32";
     case Token::Type::kIf:
@@ -185,8 +177,6 @@
       return "import";
     case Token::Type::kIn:
       return "in";
-    case Token::Type::kInstanceIdx:
-      return "instance_idx";
     case Token::Type::kIsNan:
       return "is_nan";
     case Token::Type::kIsInf:
@@ -197,10 +187,6 @@
       return "is_normal";
     case Token::Type::kKill:
       return "kill";
-    case Token::Type::kLocalInvocationId:
-      return "local_invocation_id";
-    case Token::Type::kLocalInvocationIdx:
-      return "local_invocation_idx";
     case Token::Type::kLocation:
       return "location";
     case Token::Type::kLoop:
@@ -223,16 +209,12 @@
       return "mat4x3";
     case Token::Type::kMat4x4:
       return "mat4x4";
-    case Token::Type::kNumWorkgroups:
-      return "num_workgroups";
     case Token::Type::kOffset:
       return "offset";
     case Token::Type::kOut:
       return "out";
     case Token::Type::kOuterProduct:
       return "outer_product";
-    case Token::Type::kPosition:
-      return "position";
     case Token::Type::kPremerge:
       return "premerge";
     case Token::Type::kPrivate:
@@ -273,14 +255,10 @@
       return "vec4";
     case Token::Type::kVertex:
       return "vertex";
-    case Token::Type::kVertexIdx:
-      return "vertex_idx";
     case Token::Type::kVoid:
       return "void";
     case Token::Type::kWorkgroup:
       return "workgroup";
-    case Token::Type::kWorkgroupSize:
-      return "workgroup_size";
   }
 
   return "<unknown>";
diff --git a/src/reader/wgsl/token.h b/src/reader/wgsl/token.h
index 1953f6f..53a37cd 100644
--- a/src/reader/wgsl/token.h
+++ b/src/reader/wgsl/token.h
@@ -172,20 +172,12 @@
     kFine,
     /// A 'fn'
     kFn,
-    /// A 'frag_coord'
-    kFragCoord,
-    // A 'frag_depth'
-    kFragDepth,
     /// A 'fragment'
     kFragment,
-    /// A 'front_facing'
-    kFrontFacing,
     /// A 'function'
     kFunction,
     /// A 'fwidth'
     kFwidth,
-    /// A 'global_invocation_id'
-    kGlobalInvocationId,
     /// A 'i32'
     kI32,
     /// A 'if'
@@ -196,8 +188,6 @@
     kImport,
     /// A 'in'
     kIn,
-    /// A 'instance_idx'
-    kInstanceIdx,
     /// A 'is_nan'
     kIsNan,
     /// A 'is_inf'
@@ -208,10 +198,6 @@
     kIsNormal,
     /// A 'kill'
     kKill,
-    /// A 'local_invocation_id'
-    kLocalInvocationId,
-    /// A 'local_invocation_idx'
-    kLocalInvocationIdx,
     /// A 'location'
     kLocation,
     /// A 'loop'
@@ -234,16 +220,12 @@
     kMat4x3,
     /// A 'mat4x4'
     kMat4x4,
-    /// A 'num_workgroups'
-    kNumWorkgroups,
     /// A 'offset'
     kOffset,
     /// A 'out'
     kOut,
     /// A 'outer_product'
     kOuterProduct,
-    /// A 'position'
-    kPosition,
     /// A 'premerge'
     kPremerge,
     /// A 'private'
@@ -284,14 +266,10 @@
     kVec4,
     /// A 'vertex'
     kVertex,
-    /// A 'vertex_idx'
-    kVertexIdx,
     /// A 'void'
     kVoid,
     /// A 'workgroup'
-    kWorkgroup,
-    /// A 'workgroup_size'
-    kWorkgroupSize
+    kWorkgroup
   };
 
   /// Converts a token type to a name
@@ -479,22 +457,12 @@
   bool IsFine() const { return type_ == Type::kFine; }
   /// @returns true if token is a 'fn'
   bool IsFn() const { return type_ == Type::kFn; }
-  /// @returns true if token is a 'frag_coord'
-  bool IsFragCoord() const { return type_ == Type::kFragCoord; }
-  /// @returns true if token is a 'frag_depth'
-  bool IsFragDepth() const { return type_ == Type::kFragDepth; }
   /// @returns true if token is a 'fragment'
   bool IsFragment() const { return type_ == Type::kFragment; }
-  /// @returns true if token is a 'front_facing'
-  bool IsFrontFacing() const { return type_ == Type::kFrontFacing; }
   /// @returns true if token is a 'function'
   bool IsFunction() const { return type_ == Type::kFunction; }
   /// @returns true if token is a 'fwidth'
   bool IsFwidth() const { return type_ == Type::kFwidth; }
-  /// @returns true if token is a 'global_invocation_id'
-  bool IsGlobalInvocationId() const {
-    return type_ == Type::kGlobalInvocationId;
-  }
   /// @returns true if token is a 'i32'
   bool IsI32() const { return type_ == Type::kI32; }
   /// @returns true if token is a 'if'
@@ -505,8 +473,6 @@
   bool IsImport() const { return type_ == Type::kImport; }
   /// @returns true if token is a 'in'
   bool IsIn() const { return type_ == Type::kIn; }
-  /// @returns true if token is a 'instance_idx'
-  bool IsInstanceIdx() const { return type_ == Type::kInstanceIdx; }
   /// @returns true if token is a 'is_nan'
   bool IsIsNan() const { return type_ == Type::kIsNan; }
   /// @returns true if token is a 'is_inf'
@@ -517,12 +483,6 @@
   bool IsIsNormal() const { return type_ == Type::kIsNormal; }
   /// @returns true if token is a 'kill'
   bool IsKill() const { return type_ == Type::kKill; }
-  /// @returns true if token is a 'local_invocation_id'
-  bool IsLocalInvocationId() const { return type_ == Type::kLocalInvocationId; }
-  /// @returns true if token is a 'local_invocation_idx'
-  bool IsLocalInvocationIdx() const {
-    return type_ == Type::kLocalInvocationIdx;
-  }
   /// @returns true if token is a 'location'
   bool IsLocation() const { return type_ == Type::kLocation; }
   /// @returns true if token is a 'loop'
@@ -545,16 +505,12 @@
   bool IsMat4x3() const { return type_ == Type::kMat4x3; }
   /// @returns true if token is a 'mat4x4'
   bool IsMat4x4() const { return type_ == Type::kMat4x4; }
-  /// @returns true if token is a 'num_workgroups'
-  bool IsNumWorkgroups() const { return type_ == Type::kNumWorkgroups; }
   /// @returns true if token is a 'offset'
   bool IsOffset() const { return type_ == Type::kOffset; }
   /// @returns true if token is a 'out'
   bool IsOut() const { return type_ == Type::kOut; }
   /// @returns true if token is a 'outer_product'
   bool IsOuterProduct() const { return type_ == Type::kOuterProduct; }
-  /// @returns true if token is a 'position'
-  bool IsPosition() const { return type_ == Type::kPosition; }
   /// @returns true if token is a 'private'
   bool IsPrivate() const { return type_ == Type::kPrivate; }
   /// @returns true if token is a 'ptr'
@@ -591,14 +547,10 @@
   bool IsVec4() const { return type_ == Type::kVec4; }
   /// @returns true if token is a 'vertex'
   bool IsVertex() const { return type_ == Type::kVertex; }
-  /// @returns true if token is a 'vertex_idx'
-  bool IsVertexIdx() const { return type_ == Type::kVertexIdx; }
   /// @returns true if token is a 'void'
   bool IsVoid() const { return type_ == Type::kVoid; }
   /// @returns true if token is a 'workgroup'
   bool IsWorkgroup() const { return type_ == Type::kWorkgroup; }
-  /// @returns true if token is a 'workgroup_size'
-  bool IsWorkgroupSize() const { return type_ == Type::kWorkgroupSize; }
 
   /// @returns the source line of the token
   size_t line() const { return source_.line; }