[wgsl-reader] Parsing sampler type
Change-Id: I58a3218a5d0b7ccbe6422340c94cdf3dc1bdf17a
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28000
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 3bcfdef..a154634 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -908,6 +908,7 @@
"src/reader/wgsl/parser_impl_postfix_expression_test.cc",
"src/reader/wgsl/parser_impl_primary_expression_test.cc",
"src/reader/wgsl/parser_impl_relational_expression_test.cc",
+ "src/reader/wgsl/parser_impl_sampler_type_test.cc",
"src/reader/wgsl/parser_impl_shift_expression_test.cc",
"src/reader/wgsl/parser_impl_statement_test.cc",
"src/reader/wgsl/parser_impl_statements_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9e767ba..be615c8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -439,6 +439,7 @@
reader/wgsl/parser_impl_postfix_expression_test.cc
reader/wgsl/parser_impl_primary_expression_test.cc
reader/wgsl/parser_impl_relational_expression_test.cc
+ reader/wgsl/parser_impl_sampler_type_test.cc
reader/wgsl/parser_impl_shift_expression_test.cc
reader/wgsl/parser_impl_statement_test.cc
reader/wgsl/parser_impl_statements_test.cc
diff --git a/src/reader/wgsl/lexer.cc b/src/reader/wgsl/lexer.cc
index 981ea69..71da0f6 100644
--- a/src/reader/wgsl/lexer.cc
+++ b/src/reader/wgsl/lexer.cc
@@ -561,6 +561,10 @@
return {Token::Type::kPtr, source, "ptr"};
if (str == "return")
return {Token::Type::kReturn, source, "return"};
+ if (str == "sampler")
+ return {Token::Type::kSampler, source, "sampler"};
+ if (str == "sampler_comparison")
+ return {Token::Type::kComparisonSampler, source, "sampler_comparison"};
if (str == "set")
return {Token::Type::kSet, source, "set"};
if (str == "storage_buffer")
diff --git a/src/reader/wgsl/lexer_test.cc b/src/reader/wgsl/lexer_test.cc
index c2edd00..9023b4a 100644
--- a/src/reader/wgsl/lexer_test.cc
+++ b/src/reader/wgsl/lexer_test.cc
@@ -411,70 +411,72 @@
INSTANTIATE_TEST_SUITE_P(
LexerTest,
KeywordTest,
- testing::Values(TokenData{"array", Token::Type::kArray},
- TokenData{"as", Token::Type::kAs},
- TokenData{"binding", Token::Type::kBinding},
- TokenData{"block", Token::Type::kBlock},
- TokenData{"bool", Token::Type::kBool},
- TokenData{"break", Token::Type::kBreak},
- TokenData{"builtin", Token::Type::kBuiltin},
- TokenData{"case", Token::Type::kCase},
- TokenData{"cast", Token::Type::kCast},
- TokenData{"compute", Token::Type::kCompute},
- TokenData{"const", Token::Type::kConst},
- TokenData{"continue", Token::Type::kContinue},
- TokenData{"continuing", Token::Type::kContinuing},
- TokenData{"default", Token::Type::kDefault},
- TokenData{"discard", Token::Type::kDiscard},
- TokenData{"else", Token::Type::kElse},
- TokenData{"elseif", Token::Type::kElseIf},
- TokenData{"entry_point", Token::Type::kEntryPoint},
- TokenData{"f32", Token::Type::kF32},
- TokenData{"fallthrough", Token::Type::kFallthrough},
- TokenData{"false", Token::Type::kFalse},
- TokenData{"fn", Token::Type::kFn},
- TokenData{"for", Token::Type::kFor},
- TokenData{"fragment", Token::Type::kFragment},
- TokenData{"function", Token::Type::kFunction},
- 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{"location", Token::Type::kLocation},
- TokenData{"loop", Token::Type::kLoop},
- TokenData{"mat2x2", Token::Type::kMat2x2},
- TokenData{"mat2x3", Token::Type::kMat2x3},
- TokenData{"mat2x4", Token::Type::kMat2x4},
- TokenData{"mat3x2", Token::Type::kMat3x2},
- TokenData{"mat3x3", Token::Type::kMat3x3},
- TokenData{"mat3x4", Token::Type::kMat3x4},
- TokenData{"mat4x2", Token::Type::kMat4x2},
- TokenData{"mat4x3", Token::Type::kMat4x3},
- TokenData{"mat4x4", Token::Type::kMat4x4},
- TokenData{"offset", Token::Type::kOffset},
- TokenData{"out", Token::Type::kOut},
- TokenData{"private", Token::Type::kPrivate},
- TokenData{"ptr", Token::Type::kPtr},
- TokenData{"return", Token::Type::kReturn},
- TokenData{"set", Token::Type::kSet},
- TokenData{"storage_buffer", Token::Type::kStorageBuffer},
- TokenData{"stride", Token::Type::kStride},
- TokenData{"struct", Token::Type::kStruct},
- TokenData{"switch", Token::Type::kSwitch},
- TokenData{"true", Token::Type::kTrue},
- TokenData{"type", Token::Type::kType},
- TokenData{"u32", Token::Type::kU32},
- TokenData{"uniform", Token::Type::kUniform},
- TokenData{"uniform_constant",
- Token::Type::kUniformConstant},
- TokenData{"var", Token::Type::kVar},
- TokenData{"vec2", Token::Type::kVec2},
- TokenData{"vec3", Token::Type::kVec3},
- TokenData{"vec4", Token::Type::kVec4},
- TokenData{"vertex", Token::Type::kVertex},
- TokenData{"void", Token::Type::kVoid},
- TokenData{"workgroup", Token::Type::kWorkgroup}));
+ testing::Values(
+ TokenData{"array", Token::Type::kArray},
+ TokenData{"as", Token::Type::kAs},
+ TokenData{"binding", Token::Type::kBinding},
+ TokenData{"block", Token::Type::kBlock},
+ TokenData{"bool", Token::Type::kBool},
+ TokenData{"break", Token::Type::kBreak},
+ TokenData{"builtin", Token::Type::kBuiltin},
+ TokenData{"case", Token::Type::kCase},
+ TokenData{"cast", Token::Type::kCast},
+ TokenData{"compute", Token::Type::kCompute},
+ TokenData{"const", Token::Type::kConst},
+ TokenData{"continue", Token::Type::kContinue},
+ TokenData{"continuing", Token::Type::kContinuing},
+ TokenData{"default", Token::Type::kDefault},
+ TokenData{"discard", Token::Type::kDiscard},
+ TokenData{"else", Token::Type::kElse},
+ TokenData{"elseif", Token::Type::kElseIf},
+ TokenData{"entry_point", Token::Type::kEntryPoint},
+ TokenData{"f32", Token::Type::kF32},
+ TokenData{"fallthrough", Token::Type::kFallthrough},
+ TokenData{"false", Token::Type::kFalse},
+ TokenData{"fn", Token::Type::kFn},
+ TokenData{"for", Token::Type::kFor},
+ TokenData{"fragment", Token::Type::kFragment},
+ TokenData{"function", Token::Type::kFunction},
+ 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{"location", Token::Type::kLocation},
+ TokenData{"loop", Token::Type::kLoop},
+ TokenData{"mat2x2", Token::Type::kMat2x2},
+ TokenData{"mat2x3", Token::Type::kMat2x3},
+ TokenData{"mat2x4", Token::Type::kMat2x4},
+ TokenData{"mat3x2", Token::Type::kMat3x2},
+ TokenData{"mat3x3", Token::Type::kMat3x3},
+ TokenData{"mat3x4", Token::Type::kMat3x4},
+ TokenData{"mat4x2", Token::Type::kMat4x2},
+ TokenData{"mat4x3", Token::Type::kMat4x3},
+ TokenData{"mat4x4", Token::Type::kMat4x4},
+ TokenData{"offset", Token::Type::kOffset},
+ TokenData{"out", Token::Type::kOut},
+ TokenData{"private", Token::Type::kPrivate},
+ TokenData{"ptr", Token::Type::kPtr},
+ TokenData{"return", Token::Type::kReturn},
+ TokenData{"sampler", Token::Type::kSampler},
+ TokenData{"sampler_comparison", Token::Type::kComparisonSampler},
+ TokenData{"set", Token::Type::kSet},
+ TokenData{"storage_buffer", Token::Type::kStorageBuffer},
+ TokenData{"stride", Token::Type::kStride},
+ TokenData{"struct", Token::Type::kStruct},
+ TokenData{"switch", Token::Type::kSwitch},
+ TokenData{"true", Token::Type::kTrue},
+ TokenData{"type", Token::Type::kType},
+ TokenData{"u32", Token::Type::kU32},
+ TokenData{"uniform", Token::Type::kUniform},
+ TokenData{"uniform_constant", Token::Type::kUniformConstant},
+ TokenData{"var", Token::Type::kVar},
+ TokenData{"vec2", Token::Type::kVec2},
+ TokenData{"vec3", Token::Type::kVec3},
+ TokenData{"vec4", Token::Type::kVec4},
+ TokenData{"vertex", Token::Type::kVertex},
+ TokenData{"void", Token::Type::kVoid},
+ 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 fdc9df7..33debd9 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -50,6 +50,7 @@
#include "src/ast/type/i32_type.h"
#include "src/ast/type/matrix_type.h"
#include "src/ast/type/pointer_type.h"
+#include "src/ast/type/sampler_type.h"
#include "src/ast/type/struct_type.h"
#include "src/ast/type/u32_type.h"
#include "src/ast/type/vector_type.h"
@@ -575,6 +576,24 @@
return std::make_unique<ast::Variable>(source, name, sc, type);
}
+// sampler_type
+// : SAMPLER
+// | SAMPLER_COMPARISON
+ast::type::Type* ParserImpl::sampler_type() {
+ auto t = peek();
+ if (t.IsSampler()) {
+ next(); // Consume the peek
+ return ctx_.type_mgr().Get(std::make_unique<ast::type::SamplerType>(
+ ast::type::SamplerKind::kSampler));
+ }
+ if (t.IsComparisonSampler()) {
+ next(); // Consume the peek
+ return ctx_.type_mgr().Get(std::make_unique<ast::type::SamplerType>(
+ ast::type::SamplerKind::kComparisonSampler));
+ }
+ return nullptr;
+}
+
// variable_ident_decl
// : IDENT COLON type_decl
std::pair<std::string, ast::type::Type*> ParserImpl::variable_ident_decl() {
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index d4a7abc..7bcf639 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -150,8 +150,7 @@
/// @returns the type alias or nullptr on error
ast::type::AliasType* type_alias();
/// Parses a `type_decl` grammar element
- /// @returns the parsed Type or nullptr if none matched. The returned type
- // is owned by the TypeManager.
+ /// @returns the parsed Type or nullptr if none matched.
ast::type::Type* type_decl();
/// Parses a `storage_class` grammar element
/// @returns the storage class or StorageClass::kNone if none matched
@@ -181,6 +180,9 @@
/// Parses a `function_decl` grammar element
/// @returns the parsed function, nullptr otherwise
std::unique_ptr<ast::Function> function_decl();
+ /// Parses a `sampler_type` grammar element
+ /// @returns the parsed Type or nullptr if none matched.
+ ast::type::Type* sampler_type();
/// Parses a `function_type_decl` grammar element
/// @returns the parsed type or nullptr otherwise
ast::type::Type* function_type_decl();
diff --git a/src/reader/wgsl/parser_impl_sampler_type_test.cc b/src/reader/wgsl/parser_impl_sampler_type_test.cc
new file mode 100644
index 0000000..db71a20
--- /dev/null
+++ b/src/reader/wgsl/parser_impl_sampler_type_test.cc
@@ -0,0 +1,53 @@
+// 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/type/sampler_type.h"
+#include "src/reader/wgsl/parser_impl.h"
+#include "src/reader/wgsl/parser_impl_test_helper.h"
+
+namespace tint {
+namespace reader {
+namespace wgsl {
+namespace {
+
+TEST_F(ParserImplTest, SamplerType_Invalid) {
+ auto* p = parser("1234");
+ auto* t = p->sampler_type();
+ EXPECT_EQ(t, nullptr);
+ EXPECT_FALSE(p->has_error());
+}
+
+TEST_F(ParserImplTest, SamplerType_Sampler) {
+ auto* p = parser("sampler");
+ auto* t = p->sampler_type();
+ ASSERT_NE(t, nullptr);
+ ASSERT_TRUE(t->IsSampler());
+ EXPECT_FALSE(t->AsSampler()->IsComparison());
+ EXPECT_FALSE(p->has_error());
+}
+
+TEST_F(ParserImplTest, SamplerType_ComparisonSampler) {
+ auto* p = parser("sampler_comparison");
+ auto* t = p->sampler_type();
+ ASSERT_NE(t, nullptr);
+ ASSERT_TRUE(t->IsSampler());
+ EXPECT_TRUE(t->AsSampler()->IsComparison());
+ EXPECT_FALSE(p->has_error());
+}
+
+} // namespace
+} // namespace wgsl
+} // namespace reader
+} // namespace tint
diff --git a/src/reader/wgsl/token.cc b/src/reader/wgsl/token.cc
index 2705fd2..f878ade 100644
--- a/src/reader/wgsl/token.cc
+++ b/src/reader/wgsl/token.cc
@@ -197,6 +197,10 @@
return "ptr";
case Token::Type::kReturn:
return "return";
+ case Token::Type::kSampler:
+ return "sampler";
+ case Token::Type::kComparisonSampler:
+ return "sampler_comparison";
case Token::Type::kSet:
return "set";
case Token::Type::kStorageBuffer:
diff --git a/src/reader/wgsl/token.h b/src/reader/wgsl/token.h
index 9f9ba4a..18df905 100644
--- a/src/reader/wgsl/token.h
+++ b/src/reader/wgsl/token.h
@@ -208,6 +208,10 @@
kPtr,
/// A 'return'
kReturn,
+ /// A 'sampler'
+ kSampler,
+ /// A 'sampler_comparison'
+ kComparisonSampler,
/// A 'set'
kSet,
/// A 'storage_buffer'
@@ -465,6 +469,10 @@
bool IsPtr() const { return type_ == Type::kPtr; }
/// @returns true if token is a 'return'
bool IsReturn() const { return type_ == Type::kReturn; }
+ /// @returns true if token is a 'sampler'
+ bool IsSampler() const { return type_ == Type::kSampler; }
+ /// @returns true if token is a 'sampler_comparison'
+ bool IsComparisonSampler() const { return type_ == Type::kComparisonSampler; }
/// @returns true if token is a 'set'
bool IsSet() const { return type_ == Type::kSet; }
/// @returns true if token is a 'storage_buffer'