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>
This commit is contained in:
parent
0647d23607
commit
1d2ad81eb9
1
BUILD.gn
1
BUILD.gn
|
@ -732,7 +732,6 @@ source_set("tint_unittests_wgsl_reader_src") {
|
|||
"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",
|
||||
|
|
|
@ -363,7 +363,6 @@ if(${TINT_BUILD_WGSL_READER})
|
|||
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
|
||||
|
|
|
@ -524,20 +524,12 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
|||
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 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
|||
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 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
|||
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 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
|||
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 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
|||
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 {};
|
||||
}
|
||||
|
|
|
@ -437,26 +437,19 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
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) {
|
||||
|
|
|
@ -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 @@ std::unique_ptr<ast::Variable> ParserImpl::global_constant_decl() {
|
|||
}
|
||||
|
||||
// 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 @@ ast::VariableDecorationList ParserImpl::variable_decoration_list() {
|
|||
|
||||
// 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 @@ std::unique_ptr<ast::VariableDecoration> ParserImpl::variable_decoration() {
|
|||
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 @@ std::unique_ptr<ast::VariableDecoration> ParserImpl::variable_decoration() {
|
|||
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() {
|
||||
|
|
|
@ -117,9 +117,6 @@ class ParserImpl {
|
|||
/// 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();
|
||||
|
|
|
@ -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
|
|
@ -26,7 +26,7 @@ namespace {
|
|||
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);
|
||||
|
|
|
@ -52,23 +52,77 @@ TEST_F(ParserImplTest, VariableDecoration_Location_MissingInvalid) {
|
|||
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 @@ TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingInvalid) {
|
|||
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) {
|
||||
|
|
|
@ -161,20 +161,12 @@ std::string Token::TypeToName(Type type) {
|
|||
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 @@ std::string Token::TypeToName(Type type) {
|
|||
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 @@ std::string Token::TypeToName(Type type) {
|
|||
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 @@ std::string Token::TypeToName(Type type) {
|
|||
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 @@ std::string Token::TypeToName(Type type) {
|
|||
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>";
|
||||
|
|
|
@ -172,20 +172,12 @@ class Token {
|
|||
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 @@ class Token {
|
|||
kImport,
|
||||
/// A 'in'
|
||||
kIn,
|
||||
/// A 'instance_idx'
|
||||
kInstanceIdx,
|
||||
/// A 'is_nan'
|
||||
kIsNan,
|
||||
/// A 'is_inf'
|
||||
|
@ -208,10 +198,6 @@ class Token {
|
|||
kIsNormal,
|
||||
/// A 'kill'
|
||||
kKill,
|
||||
/// A 'local_invocation_id'
|
||||
kLocalInvocationId,
|
||||
/// A 'local_invocation_idx'
|
||||
kLocalInvocationIdx,
|
||||
/// A 'location'
|
||||
kLocation,
|
||||
/// A 'loop'
|
||||
|
@ -234,16 +220,12 @@ class Token {
|
|||
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 @@ class Token {
|
|||
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 @@ class Token {
|
|||
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 @@ class Token {
|
|||
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 @@ class Token {
|
|||
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 @@ class Token {
|
|||
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 @@ class Token {
|
|||
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; }
|
||||
|
|
Loading…
Reference in New Issue