Cleanup some strings; Reorder `attribute` rule.
This CL inlines some strings which were listed at the top of the
parser. In general, we've inlined the strings there were just a few
which ended up being declared at the top of file.
The `attribute` rule is re-ordered to sort the attributes in
alphabetical order so they're easier to locate.
The `expect_storage_class` rule is renamed `expect_address_space`
Bug: tint:1633
Change-Id: Ie659742b9758142b6971493be6d0d62a092999b9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/98262
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index 8049406..207c305 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -62,26 +62,6 @@
/// parser on error.
constexpr size_t const kMaxResynchronizeLookahead = 32;
-const char kVertexStage[] = "vertex";
-const char kFragmentStage[] = "fragment";
-const char kComputeStage[] = "compute";
-
-const char kReadAccess[] = "read";
-const char kWriteAccess[] = "write";
-const char kReadWriteAccess[] = "read_write";
-
-const char kBindingAttribute[] = "binding";
-const char kBuiltinAttribute[] = "builtin";
-const char kGroupAttribute[] = "group";
-const char kIdAttribute[] = "id";
-const char kInterpolateAttribute[] = "interpolate";
-const char kInvariantAttribute[] = "invariant";
-const char kLocationAttribute[] = "location";
-const char kSizeAttribute[] = "size";
-const char kAlignAttribute[] = "align";
-const char kStageAttribute[] = "stage";
-const char kWorkgroupSizeAttribute[] = "workgroup_size";
-
// https://gpuweb.github.io/gpuweb/wgsl.html#reserved-keywords
bool is_reserved(const Token& t) {
return t == "CompileShader" || t == "ComputeShader" || t == "DomainShader" ||
@@ -969,19 +949,23 @@
return TypedIdentifier{type.value, ident.value, ident.source};
}
+// access_mode
+// : 'read'
+// | 'write'
+// | 'read_write'
Expect<ast::Access> ParserImpl::expect_access(std::string_view use) {
auto ident = expect_ident(use);
if (ident.errored) {
return Failure::kErrored;
}
- if (ident.value == kReadAccess) {
+ if (ident.value == "read") {
return {ast::Access::kRead, ident.source};
}
- if (ident.value == kWriteAccess) {
+ if (ident.value == "write") {
return {ast::Access::kWrite, ident.source};
}
- if (ident.value == kReadWriteAccess) {
+ if (ident.value == "read_write") {
return {ast::Access::kReadWrite, ident.source};
}
@@ -998,7 +982,7 @@
auto* use = "variable declaration";
auto vq = expect_lt_gt_block(use, [&]() -> Expect<VariableQualifier> {
auto source = make_source_range();
- auto sc = expect_storage_class(use);
+ auto sc = expect_address_space(use);
if (sc.errored) {
return Failure::kErrored;
}
@@ -1152,7 +1136,7 @@
auto access = ast::Access::kUndefined;
auto subtype = expect_lt_gt_block(use, [&]() -> Expect<const ast::Type*> {
- auto sc = expect_storage_class(use);
+ auto sc = expect_address_space(use);
if (sc.errored) {
return Failure::kErrored;
}
@@ -1284,7 +1268,15 @@
return builder_.ty.mat(make_source_range_from(t.source()), subtype, columns, rows);
}
-Expect<ast::StorageClass> ParserImpl::expect_storage_class(std::string_view use) {
+// address_space
+// : 'function'
+// | 'private'
+// | 'workgroup'
+// | 'uniform'
+// | 'storage'
+//
+// Note, we also parse `push_constant` from the experimental extension
+Expect<ast::StorageClass> ParserImpl::expect_address_space(std::string_view use) {
auto& t = peek();
auto ident = expect_ident("storage class");
if (ident.errored) {
@@ -1541,17 +1533,19 @@
// : VERTEX
// | FRAGMENT
// | COMPUTE
+//
+// TODO(crbug.com/tint/1503): Remove when deprecation period is over.
Expect<ast::PipelineStage> ParserImpl::expect_pipeline_stage() {
auto& t = peek();
- if (t == kVertexStage) {
+ if (t == "vertex") {
next(); // Consume the peek
return {ast::PipelineStage::kVertex, t.source()};
}
- if (t == kFragmentStage) {
+ if (t == "fragment") {
next(); // Consume the peek
return {ast::PipelineStage::kFragment, t.source()};
}
- if (t == kComputeStage) {
+ if (t == "compute") {
next(); // Consume the peek
return {ast::PipelineStage::kCompute, t.source()};
}
@@ -3243,6 +3237,29 @@
return add_error(t, "expected attribute");
}
+// attribute
+// : ATTR 'align' PAREN_LEFT expression attrib_end
+// | ATTR 'binding' PAREN_LEFT expression attrib_end
+// | ATTR 'builtin' PAREN_LEFT builtin_value_name attrib_end
+// | ATTR 'const'
+// | ATTR 'group' PAREN_LEFT expression attrib_end
+// | ATTR 'id' PAREN_LEFT expression attrib_end
+// | ATTR 'interpolate' PAREN_LEFT interpolation_type_name attrib_end
+// | ATTR 'interpolate' PAREN_LEFT interpolation_type_name COMMA
+// interpolation_sample_name attrib_end
+// | ATTR 'invariant'
+// | ATTR 'location' PAREN_LEFT expression attrib_end
+// | ATTR 'size' PAREN_LEFT expression attrib_end
+// | ATTR 'workgroup_size' PAREN_LEFT expression attrib_end
+// | ATTR 'workgroup_size' PAREN_LEFT expression COMMA expression attrib_end
+// | ATTR 'workgroup_size' PAREN_LEFT expression COMMA expression COMMA expression attrib_end
+// | ATTR 'vertex'
+// | ATTR 'fragment'
+// | ATTR 'compute'
+//
+// attrib_end
+// : COMMA? PAREN_RIGHT
+//
Maybe<const ast::Attribute*> ParserImpl::attribute() {
using Result = Maybe<const ast::Attribute*>;
auto& t = next();
@@ -3251,8 +3268,8 @@
return Failure::kNoMatch;
}
- if (t == kLocationAttribute) {
- const char* use = "location attribute";
+ if (t == "align") {
+ const char* use = "align attribute";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
if (val.errored) {
@@ -3260,11 +3277,11 @@
}
match(Token::Type::kComma);
- return create<ast::LocationAttribute>(t.source(), val.value);
+ return create<ast::StructMemberAlignAttribute>(t.source(), val.value);
});
}
- if (t == kBindingAttribute) {
+ if (t == "binding") {
const char* use = "binding attribute";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
@@ -3277,7 +3294,29 @@
});
}
- if (t == kGroupAttribute) {
+ if (t == "builtin") {
+ return expect_paren_block("builtin attribute", [&]() -> Result {
+ auto builtin = expect_builtin();
+ if (builtin.errored) {
+ return Failure::kErrored;
+ }
+ match(Token::Type::kComma);
+
+ return create<ast::BuiltinAttribute>(t.source(), builtin.value);
+ });
+ }
+
+ if (t == "compute") {
+ return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kCompute);
+ }
+
+ // Note, `const` is not valid in a WGSL source file, it's internal only
+
+ if (t == "fragment") {
+ return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kFragment);
+ }
+
+ if (t == "group") {
const char* use = "group attribute";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
@@ -3290,7 +3329,20 @@
});
}
- if (t == kInterpolateAttribute) {
+ if (t == "id") {
+ const char* use = "id attribute";
+ return expect_paren_block(use, [&]() -> Result {
+ auto val = expect_positive_sint(use);
+ if (val.errored) {
+ return Failure::kErrored;
+ }
+ match(Token::Type::kComma);
+
+ return create<ast::IdAttribute>(t.source(), val.value);
+ });
+ }
+
+ if (t == "interpolate") {
return expect_paren_block("interpolate attribute", [&]() -> Result {
auto type = expect_interpolation_type_name();
if (type.errored) {
@@ -3314,23 +3366,69 @@
});
}
- if (t == kInvariantAttribute) {
+ if (t == "invariant") {
return create<ast::InvariantAttribute>(t.source());
}
- if (t == kBuiltinAttribute) {
- return expect_paren_block("builtin attribute", [&]() -> Result {
- auto builtin = expect_builtin();
- if (builtin.errored) {
+ if (t == "location") {
+ const char* use = "location attribute";
+ return expect_paren_block(use, [&]() -> Result {
+ auto val = expect_positive_sint(use);
+ if (val.errored) {
return Failure::kErrored;
}
-
match(Token::Type::kComma);
- return create<ast::BuiltinAttribute>(t.source(), builtin.value);
+
+ return create<ast::LocationAttribute>(t.source(), val.value);
});
}
- if (t == kWorkgroupSizeAttribute) {
+ if (t == "size") {
+ const char* use = "size attribute";
+ return expect_paren_block(use, [&]() -> Result {
+ auto val = expect_positive_sint(use);
+ if (val.errored) {
+ return Failure::kErrored;
+ }
+ match(Token::Type::kComma);
+
+ return create<ast::StructMemberSizeAttribute>(t.source(), val.value);
+ });
+ }
+
+ // TODO(crbug.com/tint/1503): Remove when deprecation period is over.
+ if (t == "stage") {
+ return expect_paren_block("stage attribute", [&]() -> Result {
+ auto stage = expect_pipeline_stage();
+ if (stage.errored) {
+ return Failure::kErrored;
+ }
+
+ std::string warning = "remove stage and use @";
+ switch (stage.value) {
+ case ast::PipelineStage::kVertex:
+ warning += "vertex";
+ break;
+ case ast::PipelineStage::kFragment:
+ warning += "fragment";
+ break;
+ case ast::PipelineStage::kCompute:
+ warning += "compute";
+ break;
+ case ast::PipelineStage::kNone:
+ break;
+ }
+ deprecated(t.source(), warning);
+
+ return create<ast::StageAttribute>(t.source(), stage.value);
+ });
+ }
+
+ if (t == "vertex") {
+ return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kVertex);
+ }
+
+ if (t == "workgroup_size") {
return expect_paren_block("workgroup_size attribute", [&]() -> Result {
const ast::Expression* x = nullptr;
const ast::Expression* y = nullptr;
@@ -3373,83 +3471,6 @@
return create<ast::WorkgroupAttribute>(t.source(), x, y, z);
});
}
-
- // TODO(crbug.com/tint/1503): Remove when deprecation period is over.
- if (t == kStageAttribute) {
- return expect_paren_block("stage attribute", [&]() -> Result {
- auto stage = expect_pipeline_stage();
- if (stage.errored) {
- return Failure::kErrored;
- }
-
- std::string warning = "remove stage and use @";
- switch (stage.value) {
- case ast::PipelineStage::kVertex:
- warning += "vertex";
- break;
- case ast::PipelineStage::kFragment:
- warning += "fragment";
- break;
- case ast::PipelineStage::kCompute:
- warning += "compute";
- break;
- case ast::PipelineStage::kNone:
- break;
- }
- deprecated(t.source(), warning);
-
- return create<ast::StageAttribute>(t.source(), stage.value);
- });
- }
- if (t == kComputeStage) {
- return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kCompute);
- }
- if (t == kVertexStage) {
- return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kVertex);
- }
- if (t == kFragmentStage) {
- return create<ast::StageAttribute>(t.source(), ast::PipelineStage::kFragment);
- }
-
- if (t == kSizeAttribute) {
- const char* use = "size attribute";
- return expect_paren_block(use, [&]() -> Result {
- auto val = expect_positive_sint(use);
- if (val.errored) {
- return Failure::kErrored;
- }
- match(Token::Type::kComma);
-
- return create<ast::StructMemberSizeAttribute>(t.source(), val.value);
- });
- }
-
- if (t == kAlignAttribute) {
- const char* use = "align attribute";
- return expect_paren_block(use, [&]() -> Result {
- auto val = expect_positive_sint(use);
- if (val.errored) {
- return Failure::kErrored;
- }
- match(Token::Type::kComma);
-
- return create<ast::StructMemberAlignAttribute>(t.source(), val.value);
- });
- }
-
- if (t == kIdAttribute) {
- const char* use = "id attribute";
- return expect_paren_block(use, [&]() -> Result {
- auto val = expect_positive_sint(use);
- if (val.errored) {
- return Failure::kErrored;
- }
- match(Token::Type::kComma);
-
- return create<ast::IdAttribute>(t.source(), val.value);
- });
- }
-
return Failure::kNoMatch;
}
diff --git a/src/tint/reader/wgsl/parser_impl.h b/src/tint/reader/wgsl/parser_impl.h
index 1befac0..40b7cc8 100644
--- a/src/tint/reader/wgsl/parser_impl.h
+++ b/src/tint/reader/wgsl/parser_impl.h
@@ -426,10 +426,10 @@
/// Parses a `type_decl` grammar element
/// @returns the parsed Type or nullptr if none matched.
Maybe<const ast::Type*> type_decl();
- /// Parses a `storage_class` grammar element, erroring on parse failure.
+ /// Parses an `address_space` grammar element, erroring on parse failure.
/// @param use a description of what was being parsed if an error was raised.
- /// @returns the storage class or StorageClass::kNone if none matched
- Expect<ast::StorageClass> expect_storage_class(std::string_view use);
+ /// @returns the address space or StorageClass::kNone if none matched
+ Expect<ast::StorageClass> expect_address_space(std::string_view use);
/// Parses a `struct_decl` grammar element.
/// @returns the struct type or nullptr on error
Maybe<const ast::Struct*> struct_decl();
diff --git a/src/tint/reader/wgsl/parser_impl_storage_class_test.cc b/src/tint/reader/wgsl/parser_impl_storage_class_test.cc
index c40752a..c6ef7eb 100644
--- a/src/tint/reader/wgsl/parser_impl_storage_class_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_storage_class_test.cc
@@ -32,7 +32,7 @@
auto params = GetParam();
auto p = parser(params.input);
- auto sc = p->expect_storage_class("test");
+ auto sc = p->expect_address_space("test");
EXPECT_FALSE(sc.errored);
EXPECT_FALSE(p->has_error());
EXPECT_EQ(sc.value, params.result);
@@ -51,7 +51,7 @@
TEST_F(ParserImplTest, StorageClass_NoMatch) {
auto p = parser("not-a-storage-class");
- auto sc = p->expect_storage_class("test");
+ auto sc = p->expect_address_space("test");
EXPECT_EQ(sc.errored, true);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:1: invalid storage class for test");