Use a context object instead of a singleton
This Cl replaces the TypeManager singleton with a context object. Bug: tint:29 Change-Id: Ia662709db1b562c34955633977ce4363f28f238e Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17780 Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
0984214d8b
commit
9981b63fa4
|
@ -17,8 +17,10 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/context.h"
|
||||
#include "src/reader/reader.h"
|
||||
#include "src/type_determiner.h"
|
||||
#include "src/type_manager.h"
|
||||
#include "src/validator.h"
|
||||
#include "src/writer/writer.h"
|
||||
|
||||
|
@ -250,6 +252,11 @@ int main(int argc, const char** argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
tint::TypeManager type_manager;
|
||||
|
||||
tint::Context ctx;
|
||||
ctx.type_mgr = &type_manager;
|
||||
|
||||
std::unique_ptr<tint::reader::Reader> reader;
|
||||
#if TINT_BUILD_WGSL_READER
|
||||
if (options.input_filename.size() > 5 &&
|
||||
|
@ -260,7 +267,7 @@ int main(int argc, const char** argv) {
|
|||
return 1;
|
||||
}
|
||||
reader = std::make_unique<tint::reader::wgsl::Parser>(
|
||||
std::string(data.begin(), data.end()));
|
||||
ctx, std::string(data.begin(), data.end()));
|
||||
}
|
||||
#endif // TINT_BUILD_WGSL_READER
|
||||
|
||||
|
@ -272,7 +279,7 @@ int main(int argc, const char** argv) {
|
|||
if (!ReadFile<uint32_t>(options.input_filename, &data)) {
|
||||
return 1;
|
||||
}
|
||||
reader = std::make_unique<tint::reader::spirv::Parser>(data);
|
||||
reader = std::make_unique<tint::reader::spirv::Parser>(ctx, data);
|
||||
}
|
||||
#endif // TINT_BUILD_SPV_READER
|
||||
|
||||
|
|
|
@ -387,6 +387,7 @@ if(${TINT_BUILD_WGSL_READER})
|
|||
reader/wgsl/parser_impl_switch_body_test.cc
|
||||
reader/wgsl/parser_impl_switch_stmt_test.cc
|
||||
reader/wgsl/parser_impl_test.cc
|
||||
reader/wgsl/parser_impl_test_helper.h
|
||||
reader/wgsl/parser_impl_type_alias_test.cc
|
||||
reader/wgsl/parser_impl_type_decl_test.cc
|
||||
reader/wgsl/parser_impl_unary_expression_test.cc
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// 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.
|
||||
|
||||
#ifndef SRC_CONTEXT_H_
|
||||
#define SRC_CONTEXT_H_
|
||||
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
|
||||
struct Context {
|
||||
TypeManager* type_mgr = nullptr;
|
||||
};
|
||||
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_CONTEXT_H_
|
|
@ -17,7 +17,7 @@
|
|||
namespace tint {
|
||||
namespace reader {
|
||||
|
||||
Reader::Reader() = default;
|
||||
Reader::Reader(const Context& ctx) : ctx_(ctx) {}
|
||||
|
||||
Reader::~Reader() = default;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "src/ast/module.h"
|
||||
#include "src/context.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
|
@ -41,12 +42,16 @@ class Reader {
|
|||
|
||||
protected:
|
||||
/// Constructor
|
||||
Reader();
|
||||
/// @param ctx the context object
|
||||
explicit Reader(const Context& ctx);
|
||||
|
||||
/// Sets the error string
|
||||
/// @param msg the error message
|
||||
void set_error(const std::string& msg) { error_ = msg; }
|
||||
|
||||
/// The Tint context object
|
||||
const Context& ctx_;
|
||||
|
||||
/// An error message, if an error was encountered
|
||||
std::string error_;
|
||||
};
|
||||
|
|
|
@ -20,8 +20,8 @@ namespace tint {
|
|||
namespace reader {
|
||||
namespace spirv {
|
||||
|
||||
Parser::Parser(const std::vector<uint32_t>& spv_binary)
|
||||
: Reader(), impl_(std::make_unique<ParserImpl>(spv_binary)) {}
|
||||
Parser::Parser(const Context& ctx, const std::vector<uint32_t>& spv_binary)
|
||||
: Reader(ctx), impl_(std::make_unique<ParserImpl>(ctx, spv_binary)) {}
|
||||
|
||||
Parser::~Parser() = default;
|
||||
|
||||
|
|
|
@ -31,8 +31,9 @@ class ParserImpl;
|
|||
class Parser : public Reader {
|
||||
public:
|
||||
/// Creates a new parser
|
||||
/// @param ctx the context object
|
||||
/// @param input the input data to parse
|
||||
explicit Parser(const std::vector<uint32_t>& input);
|
||||
Parser(const Context& ctx, const std::vector<uint32_t>& input);
|
||||
/// Destructor
|
||||
~Parser() override;
|
||||
|
||||
|
|
|
@ -44,8 +44,9 @@ const spv_target_env kTargetEnv = SPV_ENV_WEBGPU_0;
|
|||
|
||||
} // namespace
|
||||
|
||||
ParserImpl::ParserImpl(const std::vector<uint32_t>& spv_binary)
|
||||
: Reader(),
|
||||
ParserImpl::ParserImpl(const Context& ctx,
|
||||
const std::vector<uint32_t>& spv_binary)
|
||||
: Reader(ctx),
|
||||
spv_binary_(spv_binary),
|
||||
fail_stream_(&success_, &errors_),
|
||||
namer_(fail_stream_),
|
||||
|
@ -75,6 +76,11 @@ ParserImpl::ParserImpl(const std::vector<uint32_t>& spv_binary)
|
|||
ParserImpl::~ParserImpl() = default;
|
||||
|
||||
bool ParserImpl::Parse() {
|
||||
if (ctx_.type_mgr == nullptr) {
|
||||
Fail() << "Missing type manager";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!success_) {
|
||||
return false;
|
||||
}
|
||||
|
@ -125,22 +131,21 @@ ast::type::Type* ParserImpl::ConvertType(uint32_t type_id) {
|
|||
}
|
||||
|
||||
ast::type::Type* result = nullptr;
|
||||
TypeManager* tint_tm = TypeManager::Instance();
|
||||
|
||||
switch (spirv_type->kind()) {
|
||||
case spvtools::opt::analysis::Type::kVoid:
|
||||
result = tint_tm->Get(std::make_unique<ast::type::VoidType>());
|
||||
result = ctx_.type_mgr->Get(std::make_unique<ast::type::VoidType>());
|
||||
break;
|
||||
case spvtools::opt::analysis::Type::kBool:
|
||||
result = tint_tm->Get(std::make_unique<ast::type::BoolType>());
|
||||
result = ctx_.type_mgr->Get(std::make_unique<ast::type::BoolType>());
|
||||
break;
|
||||
case spvtools::opt::analysis::Type::kInteger: {
|
||||
const auto* int_ty = spirv_type->AsInteger();
|
||||
if (int_ty->width() == 32) {
|
||||
if (int_ty->IsSigned()) {
|
||||
result = tint_tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
result = ctx_.type_mgr->Get(std::make_unique<ast::type::I32Type>());
|
||||
} else {
|
||||
result = tint_tm->Get(std::make_unique<ast::type::U32Type>());
|
||||
result = ctx_.type_mgr->Get(std::make_unique<ast::type::U32Type>());
|
||||
}
|
||||
} else {
|
||||
Fail() << "unhandled integer width: " << int_ty->width();
|
||||
|
@ -150,7 +155,7 @@ ast::type::Type* ParserImpl::ConvertType(uint32_t type_id) {
|
|||
case spvtools::opt::analysis::Type::kFloat: {
|
||||
const auto* float_ty = spirv_type->AsFloat();
|
||||
if (float_ty->width() == 32) {
|
||||
result = tint_tm->Get(std::make_unique<ast::type::F32Type>());
|
||||
result = ctx_.type_mgr->Get(std::make_unique<ast::type::F32Type>());
|
||||
} else {
|
||||
Fail() << "unhandled float width: " << float_ty->width();
|
||||
}
|
||||
|
@ -161,7 +166,7 @@ ast::type::Type* ParserImpl::ConvertType(uint32_t type_id) {
|
|||
const auto num_elem = vec_ty->element_count();
|
||||
auto* ast_elem_ty = ConvertType(type_mgr_->GetId(vec_ty->element_type()));
|
||||
if (ast_elem_ty != nullptr) {
|
||||
result = tint_tm->Get(
|
||||
result = ctx_.type_mgr->Get(
|
||||
std::make_unique<ast::type::VectorType>(ast_elem_ty, num_elem));
|
||||
}
|
||||
// In the error case, we'll already have emitted a diagnostic.
|
||||
|
@ -175,7 +180,7 @@ ast::type::Type* ParserImpl::ConvertType(uint32_t type_id) {
|
|||
const auto num_columns = mat_ty->element_count();
|
||||
auto* ast_scalar_ty = ConvertType(type_mgr_->GetId(scalar_ty));
|
||||
if (ast_scalar_ty != nullptr) {
|
||||
result = tint_tm->Get(std::make_unique<ast::type::MatrixType>(
|
||||
result = ctx_.type_mgr->Get(std::make_unique<ast::type::MatrixType>(
|
||||
ast_scalar_ty, num_rows, num_columns));
|
||||
}
|
||||
// In the error case, we'll already have emitted a diagnostic.
|
||||
|
|
|
@ -45,8 +45,9 @@ namespace spirv {
|
|||
class ParserImpl : Reader {
|
||||
public:
|
||||
/// Creates a new parser
|
||||
/// @param ctx the context object
|
||||
/// @param input the input data to parse
|
||||
explicit ParserImpl(const std::vector<uint32_t>& input);
|
||||
ParserImpl(const Context& ctx, const std::vector<uint32_t>& input);
|
||||
/// Destructor
|
||||
~ParserImpl() override;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "src/ast/type/matrix_type.h"
|
||||
#include "src/ast/type/vector_type.h"
|
||||
#include "src/reader/spirv/parser_impl.h"
|
||||
#include "src/reader/spirv/parser_impl_test_helper.h"
|
||||
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
|
@ -30,231 +31,224 @@ namespace {
|
|||
|
||||
using ::testing::Eq;
|
||||
|
||||
class SpvParserTest_ConvertType : public ::testing::Test {
|
||||
void TearDown() override {
|
||||
// Clean up the type manager instance at the end of a single test.
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, PreservesExistingFailure) {
|
||||
ParserImpl p(std::vector<uint32_t>{});
|
||||
p.Fail() << "boing";
|
||||
auto* type = p.ConvertType(10);
|
||||
TEST_F(SpvParserTest, ConvertType_PreservesExistingFailure) {
|
||||
auto p = parser(std::vector<uint32_t>{});
|
||||
p->Fail() << "boing";
|
||||
auto* type = p->ConvertType(10);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_THAT(p.error(), Eq("boing"));
|
||||
EXPECT_THAT(p->error(), Eq("boing"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, RequiresInternalRepresntation) {
|
||||
ParserImpl p(std::vector<uint32_t>{});
|
||||
auto* type = p.ConvertType(10);
|
||||
TEST_F(SpvParserTest, ConvertType_RequiresInternalRepresntation) {
|
||||
auto p = parser(std::vector<uint32_t>{});
|
||||
auto* type = p->ConvertType(10);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_THAT(
|
||||
p.error(),
|
||||
p->error(),
|
||||
Eq("ConvertType called when the internal module has not been built"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, NotAnId) {
|
||||
ParserImpl p(test::Assemble("%1 = OpExtInstImport \"GLSL.std.450\""));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule()) << p.error();
|
||||
TEST_F(SpvParserTest, ConvertType_NotAnId) {
|
||||
auto p = parser(test::Assemble("%1 = OpExtInstImport \"GLSL.std.450\""));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error();
|
||||
|
||||
auto* type = p.ConvertType(10);
|
||||
auto* type = p->ConvertType(10);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_EQ(nullptr, type);
|
||||
EXPECT_THAT(p.error(), Eq("ID is not a SPIR-V type: 10"));
|
||||
EXPECT_THAT(p->error(), Eq("ID is not a SPIR-V type: 10"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, IdExistsButIsNotAType) {
|
||||
ParserImpl p(test::Assemble("%1 = OpExtInstImport \"GLSL.std.450\""));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
TEST_F(SpvParserTest, ConvertType_IdExistsButIsNotAType) {
|
||||
auto p = parser(test::Assemble("%1 = OpExtInstImport \"GLSL.std.450\""));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(1);
|
||||
auto* type = p->ConvertType(1);
|
||||
EXPECT_EQ(nullptr, type);
|
||||
EXPECT_THAT(p.error(), Eq("ID is not a SPIR-V type: 1"));
|
||||
EXPECT_THAT(p->error(), Eq("ID is not a SPIR-V type: 1"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, UnhandledType) {
|
||||
TEST_F(SpvParserTest, ConvertType_UnhandledType) {
|
||||
// Pipes are an OpenCL type. Tint doesn't support them.
|
||||
ParserImpl p(test::Assemble("%70 = OpTypePipe WriteOnly"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
auto p = parser(test::Assemble("%70 = OpTypePipe WriteOnly"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(70);
|
||||
auto* type = p->ConvertType(70);
|
||||
EXPECT_EQ(nullptr, type);
|
||||
EXPECT_THAT(p.error(), Eq("unknown SPIR-V type: 70"));
|
||||
EXPECT_THAT(p->error(), Eq("unknown SPIR-V type: 70"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, Void) {
|
||||
ParserImpl p(test::Assemble("%1 = OpTypeVoid"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
TEST_F(SpvParserTest, ConvertType_Void) {
|
||||
auto p = parser(test::Assemble("%1 = OpTypeVoid"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(1);
|
||||
auto* type = p->ConvertType(1);
|
||||
EXPECT_TRUE(type->IsVoid());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, Bool) {
|
||||
ParserImpl p(test::Assemble("%100 = OpTypeBool"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
TEST_F(SpvParserTest, ConvertType_Bool) {
|
||||
auto p = parser(test::Assemble("%100 = OpTypeBool"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(100);
|
||||
auto* type = p->ConvertType(100);
|
||||
EXPECT_TRUE(type->IsBool());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, I32) {
|
||||
ParserImpl p(test::Assemble("%2 = OpTypeInt 32 1"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
TEST_F(SpvParserTest, ConvertType_I32) {
|
||||
auto p = parser(test::Assemble("%2 = OpTypeInt 32 1"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(2);
|
||||
auto* type = p->ConvertType(2);
|
||||
EXPECT_TRUE(type->IsI32());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, U32) {
|
||||
ParserImpl p(test::Assemble("%3 = OpTypeInt 32 0"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
TEST_F(SpvParserTest, ConvertType_U32) {
|
||||
auto p = parser(test::Assemble("%3 = OpTypeInt 32 0"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(3);
|
||||
auto* type = p->ConvertType(3);
|
||||
EXPECT_TRUE(type->IsU32());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, F32) {
|
||||
ParserImpl p(test::Assemble("%4 = OpTypeFloat 32"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
TEST_F(SpvParserTest, ConvertType_F32) {
|
||||
auto p = parser(test::Assemble("%4 = OpTypeFloat 32"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(4);
|
||||
auto* type = p->ConvertType(4);
|
||||
EXPECT_TRUE(type->IsF32());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, BadIntWidth) {
|
||||
ParserImpl p(test::Assemble("%5 = OpTypeInt 17 1"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
TEST_F(SpvParserTest, ConvertType_BadIntWidth) {
|
||||
auto p = parser(test::Assemble("%5 = OpTypeInt 17 1"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(5);
|
||||
auto* type = p->ConvertType(5);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_THAT(p.error(), Eq("unhandled integer width: 17"));
|
||||
EXPECT_THAT(p->error(), Eq("unhandled integer width: 17"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, BadFloatWidth) {
|
||||
ParserImpl p(test::Assemble("%6 = OpTypeFloat 19"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
TEST_F(SpvParserTest, ConvertType_BadFloatWidth) {
|
||||
auto p = parser(test::Assemble("%6 = OpTypeFloat 19"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(6);
|
||||
auto* type = p->ConvertType(6);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_THAT(p.error(), Eq("unhandled float width: 19"));
|
||||
EXPECT_THAT(p->error(), Eq("unhandled float width: 19"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, InvalidVectorElement) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, DISABLED_ConvertType_InvalidVectorElement) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%5 = OpTypePipe ReadOnly
|
||||
%20 = OpTypeVector %5 2
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(20);
|
||||
auto* type = p->ConvertType(20);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_THAT(p.error(), Eq("unknown SPIR-V type: 5"));
|
||||
EXPECT_THAT(p->error(), Eq("unknown SPIR-V type: 5"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, VecOverF32) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, ConvertType_VecOverF32) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%float = OpTypeFloat 32
|
||||
%20 = OpTypeVector %float 2
|
||||
%30 = OpTypeVector %float 3
|
||||
%40 = OpTypeVector %float 4
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* v2xf32 = p.ConvertType(20);
|
||||
auto* v2xf32 = p->ConvertType(20);
|
||||
EXPECT_TRUE(v2xf32->IsVector());
|
||||
EXPECT_TRUE(v2xf32->AsVector()->type()->IsF32());
|
||||
EXPECT_EQ(v2xf32->AsVector()->size(), 2u);
|
||||
|
||||
auto* v3xf32 = p.ConvertType(30);
|
||||
auto* v3xf32 = p->ConvertType(30);
|
||||
EXPECT_TRUE(v3xf32->IsVector());
|
||||
EXPECT_TRUE(v3xf32->AsVector()->type()->IsF32());
|
||||
EXPECT_EQ(v3xf32->AsVector()->size(), 3u);
|
||||
|
||||
auto* v4xf32 = p.ConvertType(40);
|
||||
auto* v4xf32 = p->ConvertType(40);
|
||||
EXPECT_TRUE(v4xf32->IsVector());
|
||||
EXPECT_TRUE(v4xf32->AsVector()->type()->IsF32());
|
||||
EXPECT_EQ(v4xf32->AsVector()->size(), 4u);
|
||||
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, VecOverI32) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, ConvertType_VecOverI32) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%int = OpTypeInt 32 1
|
||||
%20 = OpTypeVector %int 2
|
||||
%30 = OpTypeVector %int 3
|
||||
%40 = OpTypeVector %int 4
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* v2xi32 = p.ConvertType(20);
|
||||
auto* v2xi32 = p->ConvertType(20);
|
||||
EXPECT_TRUE(v2xi32->IsVector());
|
||||
EXPECT_TRUE(v2xi32->AsVector()->type()->IsI32());
|
||||
EXPECT_EQ(v2xi32->AsVector()->size(), 2u);
|
||||
|
||||
auto* v3xi32 = p.ConvertType(30);
|
||||
auto* v3xi32 = p->ConvertType(30);
|
||||
EXPECT_TRUE(v3xi32->IsVector());
|
||||
EXPECT_TRUE(v3xi32->AsVector()->type()->IsI32());
|
||||
EXPECT_EQ(v3xi32->AsVector()->size(), 3u);
|
||||
|
||||
auto* v4xi32 = p.ConvertType(40);
|
||||
auto* v4xi32 = p->ConvertType(40);
|
||||
EXPECT_TRUE(v4xi32->IsVector());
|
||||
EXPECT_TRUE(v4xi32->AsVector()->type()->IsI32());
|
||||
EXPECT_EQ(v4xi32->AsVector()->size(), 4u);
|
||||
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, VecOverU32) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, ConvertType_VecOverU32) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%uint = OpTypeInt 32 0
|
||||
%20 = OpTypeVector %uint 2
|
||||
%30 = OpTypeVector %uint 3
|
||||
%40 = OpTypeVector %uint 4
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* v2xu32 = p.ConvertType(20);
|
||||
auto* v2xu32 = p->ConvertType(20);
|
||||
EXPECT_TRUE(v2xu32->IsVector());
|
||||
EXPECT_TRUE(v2xu32->AsVector()->type()->IsU32());
|
||||
EXPECT_EQ(v2xu32->AsVector()->size(), 2u);
|
||||
|
||||
auto* v3xu32 = p.ConvertType(30);
|
||||
auto* v3xu32 = p->ConvertType(30);
|
||||
EXPECT_TRUE(v3xu32->IsVector());
|
||||
EXPECT_TRUE(v3xu32->AsVector()->type()->IsU32());
|
||||
EXPECT_EQ(v3xu32->AsVector()->size(), 3u);
|
||||
|
||||
auto* v4xu32 = p.ConvertType(40);
|
||||
auto* v4xu32 = p->ConvertType(40);
|
||||
EXPECT_TRUE(v4xu32->IsVector());
|
||||
EXPECT_TRUE(v4xu32->AsVector()->type()->IsU32());
|
||||
EXPECT_EQ(v4xu32->AsVector()->size(), 4u);
|
||||
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, InvalidMatrixElement) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, DISABLED_ConvertType_InvalidMatrixElement) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%5 = OpTypePipe ReadOnly
|
||||
%10 = OpTypeVector %5 2
|
||||
%20 = OpTypeMatrix %10 2
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* type = p.ConvertType(20);
|
||||
auto* type = p->ConvertType(20);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
EXPECT_THAT(p.error(), Eq("unknown SPIR-V type: 5"));
|
||||
EXPECT_THAT(p->error(), Eq("unknown SPIR-V type: 5"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_ConvertType, MatrixOverF32) {
|
||||
TEST_F(SpvParserTest, ConvertType_MatrixOverF32) {
|
||||
// Matrices are only defined over floats.
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%float = OpTypeFloat 32
|
||||
%v2 = OpTypeVector %float 2
|
||||
%v3 = OpTypeVector %float 3
|
||||
|
@ -271,63 +265,63 @@ TEST_F(SpvParserTest_ConvertType, MatrixOverF32) {
|
|||
%43 = OpTypeMatrix %v4 3
|
||||
%44 = OpTypeMatrix %v4 4
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
|
||||
auto* m22 = p.ConvertType(22);
|
||||
auto* m22 = p->ConvertType(22);
|
||||
EXPECT_TRUE(m22->IsMatrix());
|
||||
EXPECT_TRUE(m22->AsMatrix()->type()->IsF32());
|
||||
EXPECT_EQ(m22->AsMatrix()->rows(), 2);
|
||||
EXPECT_EQ(m22->AsMatrix()->columns(), 2);
|
||||
|
||||
auto* m23 = p.ConvertType(23);
|
||||
auto* m23 = p->ConvertType(23);
|
||||
EXPECT_TRUE(m23->IsMatrix());
|
||||
EXPECT_TRUE(m23->AsMatrix()->type()->IsF32());
|
||||
EXPECT_EQ(m23->AsMatrix()->rows(), 2);
|
||||
EXPECT_EQ(m23->AsMatrix()->columns(), 3);
|
||||
|
||||
auto* m24 = p.ConvertType(24);
|
||||
auto* m24 = p->ConvertType(24);
|
||||
EXPECT_TRUE(m24->IsMatrix());
|
||||
EXPECT_TRUE(m24->AsMatrix()->type()->IsF32());
|
||||
EXPECT_EQ(m24->AsMatrix()->rows(), 2);
|
||||
EXPECT_EQ(m24->AsMatrix()->columns(), 4);
|
||||
|
||||
auto* m32 = p.ConvertType(32);
|
||||
auto* m32 = p->ConvertType(32);
|
||||
EXPECT_TRUE(m32->IsMatrix());
|
||||
EXPECT_TRUE(m32->AsMatrix()->type()->IsF32());
|
||||
EXPECT_EQ(m32->AsMatrix()->rows(), 3);
|
||||
EXPECT_EQ(m32->AsMatrix()->columns(), 2);
|
||||
|
||||
auto* m33 = p.ConvertType(33);
|
||||
auto* m33 = p->ConvertType(33);
|
||||
EXPECT_TRUE(m33->IsMatrix());
|
||||
EXPECT_TRUE(m33->AsMatrix()->type()->IsF32());
|
||||
EXPECT_EQ(m33->AsMatrix()->rows(), 3);
|
||||
EXPECT_EQ(m33->AsMatrix()->columns(), 3);
|
||||
|
||||
auto* m34 = p.ConvertType(34);
|
||||
auto* m34 = p->ConvertType(34);
|
||||
EXPECT_TRUE(m34->IsMatrix());
|
||||
EXPECT_TRUE(m34->AsMatrix()->type()->IsF32());
|
||||
EXPECT_EQ(m34->AsMatrix()->rows(), 3);
|
||||
EXPECT_EQ(m34->AsMatrix()->columns(), 4);
|
||||
|
||||
auto* m42 = p.ConvertType(42);
|
||||
auto* m42 = p->ConvertType(42);
|
||||
EXPECT_TRUE(m42->IsMatrix());
|
||||
EXPECT_TRUE(m42->AsMatrix()->type()->IsF32());
|
||||
EXPECT_EQ(m42->AsMatrix()->rows(), 4);
|
||||
EXPECT_EQ(m42->AsMatrix()->columns(), 2);
|
||||
|
||||
auto* m43 = p.ConvertType(43);
|
||||
auto* m43 = p->ConvertType(43);
|
||||
EXPECT_TRUE(m43->IsMatrix());
|
||||
EXPECT_TRUE(m43->AsMatrix()->type()->IsF32());
|
||||
EXPECT_EQ(m43->AsMatrix()->rows(), 4);
|
||||
EXPECT_EQ(m43->AsMatrix()->columns(), 3);
|
||||
|
||||
auto* m44 = p.ConvertType(44);
|
||||
auto* m44 = p->ConvertType(44);
|
||||
EXPECT_TRUE(m44->IsMatrix());
|
||||
EXPECT_TRUE(m44->AsMatrix()->type()->IsF32());
|
||||
EXPECT_EQ(m44->AsMatrix()->rows(), 4);
|
||||
EXPECT_EQ(m44->AsMatrix()->columns(), 4);
|
||||
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/reader/spirv/parser_impl.h"
|
||||
#include "src/reader/spirv/parser_impl_test_helper.h"
|
||||
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -25,8 +26,6 @@ namespace {
|
|||
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
using SpvParserTest_EntryPoint = ::testing::Test;
|
||||
|
||||
std::string MakeEntryPoint(const std::string& stage,
|
||||
const std::string& name,
|
||||
const std::string& id = "42") {
|
||||
|
@ -35,55 +34,55 @@ std::string MakeEntryPoint(const std::string& stage,
|
|||
"%" + id + " = OpTypeVoid\n";
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_EntryPoint, NoEntryPoint) {
|
||||
ParserImpl p(test::Assemble(""));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
const auto module_ast = p.module().to_str();
|
||||
TEST_F(SpvParserTest, EntryPoint_NoEntryPoint) {
|
||||
auto p = parser(test::Assemble(""));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_ast = p->module().to_str();
|
||||
EXPECT_THAT(module_ast, Not(HasSubstr("EntryPoint")));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_EntryPoint, Vertex) {
|
||||
ParserImpl p(test::Assemble(MakeEntryPoint("Vertex", "foobar")));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
const auto module_str = p.module().to_str();
|
||||
TEST_F(SpvParserTest, EntryPoint_Vertex) {
|
||||
auto p = parser(test::Assemble(MakeEntryPoint("Vertex", "foobar")));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = p->module().to_str();
|
||||
EXPECT_THAT(module_str, HasSubstr(R"(EntryPoint{vertex = foobar})"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_EntryPoint, Fragment) {
|
||||
ParserImpl p(test::Assemble(MakeEntryPoint("Fragment", "blitz")));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
const auto module_str = p.module().to_str();
|
||||
TEST_F(SpvParserTest, EntryPoint_Fragment) {
|
||||
auto p = parser(test::Assemble(MakeEntryPoint("Fragment", "blitz")));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = p->module().to_str();
|
||||
EXPECT_THAT(module_str, HasSubstr(R"(EntryPoint{fragment = blitz})"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_EntryPoint, Compute) {
|
||||
ParserImpl p(test::Assemble(MakeEntryPoint("GLCompute", "sort")));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
const auto module_str = p.module().to_str();
|
||||
TEST_F(SpvParserTest, EntryPoint_Compute) {
|
||||
auto p = parser(test::Assemble(MakeEntryPoint("GLCompute", "sort")));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = p->module().to_str();
|
||||
EXPECT_THAT(module_str, HasSubstr(R"(EntryPoint{compute = sort})"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_EntryPoint, MultiNameConflict) {
|
||||
ParserImpl p(test::Assemble(MakeEntryPoint("GLCompute", "work", "40") +
|
||||
TEST_F(SpvParserTest, EntryPoint_MultiNameConflict) {
|
||||
auto p = parser(test::Assemble(MakeEntryPoint("GLCompute", "work", "40") +
|
||||
MakeEntryPoint("Vertex", "work", "50") +
|
||||
MakeEntryPoint("Fragment", "work", "60")));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
const auto module_str = p.module().to_str();
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = p->module().to_str();
|
||||
EXPECT_THAT(module_str, HasSubstr(R"(EntryPoint{compute = work})"));
|
||||
EXPECT_THAT(module_str, HasSubstr(R"(EntryPoint{vertex = work_1})"));
|
||||
EXPECT_THAT(module_str, HasSubstr(R"(EntryPoint{fragment = work_2})"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest_EntryPoint, NameIsSanitized) {
|
||||
ParserImpl p(test::Assemble(MakeEntryPoint("GLCompute", ".1234")));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
const auto module_str = p.module().to_str();
|
||||
TEST_F(SpvParserTest, EntryPoint_NameIsSanitized) {
|
||||
auto p = parser(test::Assemble(MakeEntryPoint("GLCompute", ".1234")));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = p->module().to_str();
|
||||
EXPECT_THAT(module_str, HasSubstr(R"(EntryPoint{compute = x_1234})"));
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/reader/spirv/parser_impl.h"
|
||||
#include "src/reader/spirv/parser_impl_test_helper.h"
|
||||
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -30,34 +31,32 @@ using ::testing::HasSubstr;
|
|||
using ::testing::Not;
|
||||
using ::testing::UnorderedElementsAre;
|
||||
|
||||
using SpvParseImport = ::testing::Test;
|
||||
|
||||
TEST_F(SpvParseImport, NoImport) {
|
||||
ParserImpl p(test::Assemble("%1 = OpTypeVoid"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
const auto module_ast = p.module().to_str();
|
||||
TEST_F(SpvParserTest, Import_NoImport) {
|
||||
auto p = parser(test::Assemble("%1 = OpTypeVoid"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_ast = p->module().to_str();
|
||||
EXPECT_THAT(module_ast, Not(HasSubstr("Import")));
|
||||
}
|
||||
|
||||
TEST_F(SpvParseImport, ImportGlslStd450) {
|
||||
ParserImpl p(test::Assemble(R"(%1 = OpExtInstImport "GLSL.std.450")"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_THAT(p.glsl_std_450_imports(), ElementsAre(1));
|
||||
const auto module_ast = p.module().to_str();
|
||||
TEST_F(SpvParserTest, Import_ImportGlslStd450) {
|
||||
auto p = parser(test::Assemble(R"(%1 = OpExtInstImport "GLSL.std.450")"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
EXPECT_THAT(p->glsl_std_450_imports(), ElementsAre(1));
|
||||
const auto module_ast = p->module().to_str();
|
||||
EXPECT_THAT(module_ast, HasSubstr(R"(Import{"GLSL.std.450" as std::glsl})"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParseImport, ImportGlslStd450Twice) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, Import_ImportGlslStd450Twice) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
%42 = OpExtInstImport "GLSL.std.450"
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p.error().empty());
|
||||
EXPECT_THAT(p.glsl_std_450_imports(), UnorderedElementsAre(1, 42));
|
||||
const auto module = p.module();
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
EXPECT_THAT(p->glsl_std_450_imports(), UnorderedElementsAre(1, 42));
|
||||
const auto module = p->module();
|
||||
EXPECT_EQ(module.imports().size(), 1);
|
||||
const auto module_ast = module.to_str();
|
||||
// TODO(dneto): Use a matcher to show there is only one import.
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/reader/spirv/parser_impl_test_helper.h"
|
||||
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -28,23 +29,21 @@ namespace {
|
|||
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
using SpvParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(SpvParserImplTest, Uint32VecEmpty) {
|
||||
TEST_F(SpvParserTest, Impl_Uint32VecEmpty) {
|
||||
std::vector<uint32_t> data;
|
||||
ParserImpl p{data};
|
||||
EXPECT_FALSE(p.Parse());
|
||||
auto p = parser(data);
|
||||
EXPECT_FALSE(p->Parse());
|
||||
// TODO(dneto): What message?
|
||||
}
|
||||
|
||||
TEST_F(SpvParserImplTest, InvalidModuleFails) {
|
||||
TEST_F(SpvParserTest, Impl_InvalidModuleFails) {
|
||||
auto invalid_spv = test::Assemble("%ty = OpTypeInt 3 0");
|
||||
ParserImpl p{invalid_spv};
|
||||
EXPECT_FALSE(p.Parse());
|
||||
auto p = parser(invalid_spv);
|
||||
EXPECT_FALSE(p->Parse());
|
||||
EXPECT_THAT(
|
||||
p.error(),
|
||||
p->error(),
|
||||
HasSubstr("TypeInt cannot appear before the memory model instruction"));
|
||||
EXPECT_THAT(p.error(), HasSubstr("OpTypeInt 3 0"));
|
||||
EXPECT_THAT(p->error(), HasSubstr("OpTypeInt 3 0"));
|
||||
}
|
||||
|
||||
// TODO(dneto): uint32 vec, valid SPIR-V
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
// 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.
|
||||
|
||||
#ifndef SRC_READER_SPIRV_PARSER_IMPL_TEST_HELPER_H_
|
||||
#define SRC_READER_SPIRV_PARSER_IMPL_TEST_HELPER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/context.h"
|
||||
#include "src/reader/spirv/parser_impl.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace spirv {
|
||||
|
||||
class SpvParserTest : public testing::Test {
|
||||
public:
|
||||
SpvParserTest() = default;
|
||||
~SpvParserTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = nullptr;
|
||||
}
|
||||
|
||||
ParserImpl* parser(const std::vector<uint32_t>& input) {
|
||||
impl_ = std::make_unique<ParserImpl>(ctx_, input);
|
||||
return impl_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<ParserImpl> impl_;
|
||||
Context ctx_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
} // namespace spirv
|
||||
} // namespace reader
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_READER_WGSL_PARSER_IMPL_TEST_HELPER_H_
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/reader/spirv/parser_impl.h"
|
||||
#include "src/reader/spirv/parser_impl_test_helper.h"
|
||||
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -26,64 +27,62 @@ namespace {
|
|||
|
||||
using ::testing::Eq;
|
||||
|
||||
using SpvParseUserNameTest = ::testing::Test;
|
||||
|
||||
TEST_F(SpvParseUserNameTest, RespectOpName) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, UserName_RespectOpName) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpName %1 "the_void_type"
|
||||
%1 = OpTypeVoid
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p.namer().GetName(1), Eq("the_void_type"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->namer().GetName(1), Eq("the_void_type"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParseUserNameTest, DistinguishDuplicateSuggestion) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, UserName_DistinguishDuplicateSuggestion) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpName %1 "vanilla"
|
||||
OpName %2 "vanilla"
|
||||
%1 = OpTypeVoid
|
||||
%2 = OpTypeInt 32 0
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p.namer().GetName(1), Eq("vanilla"));
|
||||
EXPECT_THAT(p.namer().GetName(2), Eq("vanilla_1"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->namer().GetName(1), Eq("vanilla"));
|
||||
EXPECT_THAT(p->namer().GetName(2), Eq("vanilla_1"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParseUserNameTest, RespectOpMemberName) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, UserName_RespectOpMemberName) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpMemberName %3 0 "strawberry"
|
||||
OpMemberName %3 1 "vanilla"
|
||||
OpMemberName %3 2 "chocolate"
|
||||
%2 = OpTypeInt 32 0
|
||||
%3 = OpTypeStruct %2 %2 %2
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p.namer().GetMemberName(3, 0), Eq("strawberry"));
|
||||
EXPECT_THAT(p.namer().GetMemberName(3, 1), Eq("vanilla"));
|
||||
EXPECT_THAT(p.namer().GetMemberName(3, 2), Eq("chocolate"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->namer().GetMemberName(3, 0), Eq("strawberry"));
|
||||
EXPECT_THAT(p->namer().GetMemberName(3, 1), Eq("vanilla"));
|
||||
EXPECT_THAT(p->namer().GetMemberName(3, 2), Eq("chocolate"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParseUserNameTest, SynthesizeMemberNames) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, UserName_SynthesizeMemberNames) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%2 = OpTypeInt 32 0
|
||||
%3 = OpTypeStruct %2 %2 %2
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p.namer().GetMemberName(3, 0), Eq("field0"));
|
||||
EXPECT_THAT(p.namer().GetMemberName(3, 1), Eq("field1"));
|
||||
EXPECT_THAT(p.namer().GetMemberName(3, 2), Eq("field2"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->namer().GetMemberName(3, 0), Eq("field0"));
|
||||
EXPECT_THAT(p->namer().GetMemberName(3, 1), Eq("field1"));
|
||||
EXPECT_THAT(p->namer().GetMemberName(3, 2), Eq("field2"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParseUserNameTest, MemberNamesMixUserAndSynthesized) {
|
||||
ParserImpl p(test::Assemble(R"(
|
||||
TEST_F(SpvParserTest, UserName_MemberNamesMixUserAndSynthesized) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpMemberName %3 1 "vanilla"
|
||||
%2 = OpTypeInt 32 0
|
||||
%3 = OpTypeStruct %2 %2 %2
|
||||
)"));
|
||||
EXPECT_TRUE(p.BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p.namer().GetMemberName(3, 0), Eq("field0"));
|
||||
EXPECT_THAT(p.namer().GetMemberName(3, 1), Eq("vanilla"));
|
||||
EXPECT_THAT(p.namer().GetMemberName(3, 2), Eq("field2"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->namer().GetMemberName(3, 0), Eq("field0"));
|
||||
EXPECT_THAT(p->namer().GetMemberName(3, 1), Eq("vanilla"));
|
||||
EXPECT_THAT(p->namer().GetMemberName(3, 2), Eq("field2"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/context.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
|
@ -28,7 +29,8 @@ using ParserTest = testing::Test;
|
|||
|
||||
TEST_F(ParserTest, Uint32VecEmpty) {
|
||||
std::vector<uint32_t> data;
|
||||
Parser p{data};
|
||||
Context ctx;
|
||||
Parser p(ctx, data);
|
||||
EXPECT_FALSE(p.Parse());
|
||||
// TODO(dneto): What message?
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ namespace tint {
|
|||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
Parser::Parser(const std::string& input)
|
||||
: Reader(), impl_(std::make_unique<ParserImpl>(input)) {}
|
||||
Parser::Parser(const Context& ctx, const std::string& input)
|
||||
: Reader(ctx), impl_(std::make_unique<ParserImpl>(ctx, input)) {}
|
||||
|
||||
Parser::~Parser() = default;
|
||||
|
||||
|
|
|
@ -30,8 +30,9 @@ class ParserImpl;
|
|||
class Parser : public Reader {
|
||||
public:
|
||||
/// Creates a new parser
|
||||
/// @param ctx the context object
|
||||
/// @param input the input string to parse
|
||||
explicit Parser(const std::string& input);
|
||||
Parser(const Context& ctx, const std::string& input);
|
||||
~Parser() override;
|
||||
|
||||
/// Run the parser
|
||||
|
|
|
@ -71,8 +71,8 @@ namespace tint {
|
|||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
ParserImpl::ParserImpl(const std::string& input)
|
||||
: lexer_(std::make_unique<Lexer>(input)) {}
|
||||
ParserImpl::ParserImpl(const Context& ctx, const std::string& input)
|
||||
: ctx_(ctx), lexer_(std::make_unique<Lexer>(input)) {}
|
||||
|
||||
ParserImpl::~ParserImpl() = default;
|
||||
|
||||
|
@ -134,6 +134,11 @@ ast::type::Type* ParserImpl::get_alias(const std::string& name) {
|
|||
}
|
||||
|
||||
bool ParserImpl::Parse() {
|
||||
if (ctx_.type_mgr == nullptr) {
|
||||
set_error(peek(), "missing type manager");
|
||||
return false;
|
||||
}
|
||||
|
||||
translation_unit();
|
||||
return !has_error();
|
||||
}
|
||||
|
@ -672,8 +677,6 @@ ast::type::AliasType* ParserImpl::type_alias() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
auto tm = TypeManager::Instance();
|
||||
|
||||
auto type = type_decl();
|
||||
if (has_error())
|
||||
return nullptr;
|
||||
|
@ -687,14 +690,15 @@ ast::type::AliasType* ParserImpl::type_alias() {
|
|||
}
|
||||
|
||||
str->set_name(name);
|
||||
type = tm->Get(std::move(str));
|
||||
type = ctx_.type_mgr->Get(std::move(str));
|
||||
}
|
||||
if (type == nullptr) {
|
||||
set_error(peek(), "invalid type for alias");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto alias = tm->Get(std::make_unique<ast::type::AliasType>(name, type));
|
||||
auto alias =
|
||||
ctx_.type_mgr->Get(std::make_unique<ast::type::AliasType>(name, type));
|
||||
register_alias(name, alias);
|
||||
|
||||
return alias->AsAlias();
|
||||
|
@ -722,8 +726,6 @@ ast::type::AliasType* ParserImpl::type_alias() {
|
|||
// | MAT4x3 LESS_THAN type_decl GREATER_THAN
|
||||
// | MAT4x4 LESS_THAN type_decl GREATER_THAN
|
||||
ast::type::Type* ParserImpl::type_decl() {
|
||||
auto tm = TypeManager::Instance();
|
||||
|
||||
auto t = peek();
|
||||
if (t.IsIdentifier()) {
|
||||
next(); // Consume the peek
|
||||
|
@ -736,19 +738,19 @@ ast::type::Type* ParserImpl::type_decl() {
|
|||
}
|
||||
if (t.IsBool()) {
|
||||
next(); // Consume the peek
|
||||
return tm->Get(std::make_unique<ast::type::BoolType>());
|
||||
return ctx_.type_mgr->Get(std::make_unique<ast::type::BoolType>());
|
||||
}
|
||||
if (t.IsF32()) {
|
||||
next(); // Consume the peek
|
||||
return tm->Get(std::make_unique<ast::type::F32Type>());
|
||||
return ctx_.type_mgr->Get(std::make_unique<ast::type::F32Type>());
|
||||
}
|
||||
if (t.IsI32()) {
|
||||
next(); // Consume the peek
|
||||
return tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
return ctx_.type_mgr->Get(std::make_unique<ast::type::I32Type>());
|
||||
}
|
||||
if (t.IsU32()) {
|
||||
next(); // Consume the peek
|
||||
return tm->Get(std::make_unique<ast::type::U32Type>());
|
||||
return ctx_.type_mgr->Get(std::make_unique<ast::type::U32Type>());
|
||||
}
|
||||
if (t.IsVec2() || t.IsVec3() || t.IsVec4()) {
|
||||
return type_decl_vector(t);
|
||||
|
@ -804,7 +806,7 @@ ast::type::Type* ParserImpl::type_decl_pointer(Token t) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return TypeManager::Instance()->Get(
|
||||
return ctx_.type_mgr->Get(
|
||||
std::make_unique<ast::type::PointerType>(subtype, sc));
|
||||
}
|
||||
|
||||
|
@ -837,7 +839,7 @@ ast::type::Type* ParserImpl::type_decl_vector(Token t) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return TypeManager::Instance()->Get(
|
||||
return ctx_.type_mgr->Get(
|
||||
std::make_unique<ast::type::VectorType>(subtype, count));
|
||||
}
|
||||
|
||||
|
@ -878,7 +880,7 @@ ast::type::Type* ParserImpl::type_decl_array(Token t) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return TypeManager::Instance()->Get(
|
||||
return ctx_.type_mgr->Get(
|
||||
std::make_unique<ast::type::ArrayType>(subtype, size));
|
||||
}
|
||||
|
||||
|
@ -918,7 +920,7 @@ ast::type::Type* ParserImpl::type_decl_matrix(Token t) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return TypeManager::Instance()->Get(
|
||||
return ctx_.type_mgr->Get(
|
||||
std::make_unique<ast::type::MatrixType>(subtype, rows, columns));
|
||||
}
|
||||
|
||||
|
@ -1209,12 +1211,10 @@ std::unique_ptr<ast::Function> ParserImpl::function_decl() {
|
|||
// : type_decl
|
||||
// | VOID
|
||||
ast::type::Type* ParserImpl::function_type_decl() {
|
||||
auto tm = TypeManager::Instance();
|
||||
|
||||
auto t = peek();
|
||||
if (t.IsVoid()) {
|
||||
next(); // Consume the peek
|
||||
return tm->Get(std::make_unique<ast::type::VoidType>());
|
||||
return ctx_.type_mgr->Get(std::make_unique<ast::type::VoidType>());
|
||||
}
|
||||
return type_decl();
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "src/ast/unless_statement.h"
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/ast/variable_decoration.h"
|
||||
#include "src/context.h"
|
||||
#include "src/reader/wgsl/token.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -56,8 +57,9 @@ class Lexer;
|
|||
class ParserImpl {
|
||||
public:
|
||||
/// Creates a new parser
|
||||
/// @param ctx the context object
|
||||
/// @param input the input string to parse
|
||||
explicit ParserImpl(const std::string& input);
|
||||
ParserImpl(const Context& ctx, const std::string& input);
|
||||
~ParserImpl();
|
||||
|
||||
/// Run the parser
|
||||
|
@ -349,6 +351,7 @@ class ParserImpl {
|
|||
ast::type::Type* type_decl_array(Token t);
|
||||
ast::type::Type* type_decl_matrix(Token t);
|
||||
|
||||
const Context& ctx_;
|
||||
std::string error_;
|
||||
std::unique_ptr<Lexer> lexer_;
|
||||
std::deque<Token> token_queue_;
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
||||
ParserImpl p{"a + true"};
|
||||
auto e = p.additive_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a + true");
|
||||
auto e = p->additive_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,9 +47,9 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
|
||||
ParserImpl p{"a - true"};
|
||||
auto e = p.additive_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a - true");
|
||||
auto e = p->additive_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -70,24 +69,24 @@ TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} + true"};
|
||||
auto e = p.additive_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} + true");
|
||||
auto e = p->additive_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_InvalidRHS) {
|
||||
ParserImpl p{"true + if (a) {}"};
|
||||
auto e = p.additive_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true + if (a) {}");
|
||||
auto e = p->additive_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: unable to parse right side of + expression");
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of + expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AdditiveExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.additive_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->additive_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, AndExpression_Parses) {
|
||||
ParserImpl p{"a & true"};
|
||||
auto e = p.and_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a & true");
|
||||
auto e = p->and_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,24 +47,24 @@ TEST_F(ParserImplTest, AndExpression_Parses) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, AndExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} & true"};
|
||||
auto e = p.and_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} & true");
|
||||
auto e = p->and_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AndExpression_InvalidRHS) {
|
||||
ParserImpl p{"true & if (a) {}"};
|
||||
auto e = p.and_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true & if (a) {}");
|
||||
auto e = p->and_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: unable to parse right side of & expression");
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of & expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AndExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.and_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->and_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -21,26 +21,25 @@
|
|||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ArgumentExpressionList_Parses) {
|
||||
ParserImpl p{"a"};
|
||||
auto e = p.argument_expression_list();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a");
|
||||
auto e = p->argument_expression_list();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
|
||||
ASSERT_EQ(e.size(), 1);
|
||||
ASSERT_TRUE(e[0]->IsIdentifier());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ArgumentExpressionList_ParsesMultiple) {
|
||||
ParserImpl p{"a, -33, 1+2"};
|
||||
auto e = p.argument_expression_list();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a, -33, 1+2");
|
||||
auto e = p->argument_expression_list();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
|
||||
ASSERT_EQ(e.size(), 3);
|
||||
ASSERT_TRUE(e[0]->IsIdentifier());
|
||||
|
@ -49,17 +48,17 @@ TEST_F(ParserImplTest, ArgumentExpressionList_ParsesMultiple) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ArgumentExpressionList_HandlesMissingExpression) {
|
||||
ParserImpl p{"a, "};
|
||||
auto e = p.argument_expression_list();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:4: unable to parse argument expression after comma");
|
||||
auto p = parser("a, ");
|
||||
auto e = p->argument_expression_list();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:4: unable to parse argument expression after comma");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ArgumentExpressionList_HandlesInvalidExpression) {
|
||||
ParserImpl p{"if(a) {}"};
|
||||
auto e = p.argument_expression_list();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:1: unable to parse argument expression");
|
||||
auto p = parser("if(a) {}");
|
||||
auto e = p->argument_expression_list();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:1: unable to parse argument expression");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -21,17 +21,16 @@
|
|||
#include "src/ast/literal.h"
|
||||
#include "src/ast/member_accessor_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
|
||||
ParserImpl p{"a = 123"};
|
||||
auto e = p.assignment_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a = 123");
|
||||
auto e = p->assignment_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsAssign());
|
||||
|
@ -53,9 +52,9 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
|
||||
ParserImpl p{"a.b.c[2].d = 123"};
|
||||
auto e = p.assignment_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a.b.c[2].d = 123");
|
||||
auto e = p->assignment_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsAssign());
|
||||
|
@ -109,26 +108,26 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, AssignmentStmt_MissingEqual) {
|
||||
ParserImpl p{"a.b.c[2].d 123"};
|
||||
auto e = p.assignment_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a.b.c[2].d 123");
|
||||
auto e = p->assignment_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: missing = for assignment");
|
||||
EXPECT_EQ(p->error(), "1:12: missing = for assignment");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AssignmentStmt_InvalidLHS) {
|
||||
ParserImpl p{"if (true) {} = 123"};
|
||||
auto e = p.assignment_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (true) {} = 123");
|
||||
auto e = p->assignment_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AssignmentStmt_InvalidRHS) {
|
||||
ParserImpl p{"a.b.c[2].d = if (true) {}"};
|
||||
auto e = p.assignment_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a.b.c[2].d = if (true) {}");
|
||||
auto e = p->assignment_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: unable to parse right side of assignment");
|
||||
EXPECT_EQ(p->error(), "1:14: unable to parse right side of assignment");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -14,21 +14,20 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, BodyStmt) {
|
||||
ParserImpl p{R"({
|
||||
auto p = parser(R"({
|
||||
kill;
|
||||
nop;
|
||||
return 1 + b / 2;
|
||||
})"};
|
||||
auto e = p.body_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
})");
|
||||
auto e = p->body_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.size(), 3);
|
||||
EXPECT_TRUE(e[0]->IsKill());
|
||||
EXPECT_TRUE(e[1]->IsNop());
|
||||
|
@ -36,24 +35,24 @@ TEST_F(ParserImplTest, BodyStmt) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, BodyStmt_Empty) {
|
||||
ParserImpl p{"{}"};
|
||||
auto e = p.body_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("{}");
|
||||
auto e = p->body_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
EXPECT_EQ(e.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, BodyStmt_InvalidStmt) {
|
||||
ParserImpl p{"{fn main() -> void {}}"};
|
||||
auto e = p.body_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:2: missing }");
|
||||
auto p = parser("{fn main() -> void {}}");
|
||||
auto e = p->body_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:2: missing }");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, BodyStmt_MissingRightParen) {
|
||||
ParserImpl p{"{return;"};
|
||||
auto e = p.body_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:9: missing }");
|
||||
auto p = parser("{return;");
|
||||
auto e = p->body_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:9: missing }");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -17,17 +17,16 @@
|
|||
#include "src/ast/return_statement.h"
|
||||
#include "src/ast/statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, BreakStmt) {
|
||||
ParserImpl p{"break"};
|
||||
auto e = p.break_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("break");
|
||||
auto e = p->break_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsBreak());
|
||||
EXPECT_EQ(e->condition(), ast::StatementCondition::kNone);
|
||||
|
@ -35,9 +34,9 @@ TEST_F(ParserImplTest, BreakStmt) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, BreakStmt_WithIf) {
|
||||
ParserImpl p{"break if (a == b)"};
|
||||
auto e = p.break_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("break if (a == b)");
|
||||
auto e = p->break_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsBreak());
|
||||
EXPECT_EQ(e->condition(), ast::StatementCondition::kIf);
|
||||
|
@ -46,9 +45,9 @@ TEST_F(ParserImplTest, BreakStmt_WithIf) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, BreakStmt_WithUnless) {
|
||||
ParserImpl p{"break unless (a == b)"};
|
||||
auto e = p.break_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("break unless (a == b)");
|
||||
auto e = p->break_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsBreak());
|
||||
EXPECT_EQ(e->condition(), ast::StatementCondition::kUnless);
|
||||
|
@ -57,19 +56,19 @@ TEST_F(ParserImplTest, BreakStmt_WithUnless) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, BreakStmt_InvalidRHS) {
|
||||
ParserImpl p{"break if (a = b)"};
|
||||
auto e = p.break_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("break if (a = b)");
|
||||
auto e = p->break_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: expected )");
|
||||
EXPECT_EQ(p->error(), "1:13: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, BreakStmt_MissingRHS) {
|
||||
ParserImpl p{"break if"};
|
||||
auto e = p.break_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("break if");
|
||||
auto e = p->break_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: expected (");
|
||||
EXPECT_EQ(p->error(), "1:9: expected (");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#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 {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
namespace {
|
||||
|
||||
struct BuiltinData {
|
||||
const char* input;
|
||||
|
@ -30,16 +30,41 @@ inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
|
|||
out << std::string(data.input);
|
||||
return out;
|
||||
}
|
||||
using BuiltinTest = testing::TestWithParam<BuiltinData>;
|
||||
|
||||
class BuiltinTest : public testing::TestWithParam<BuiltinData> {
|
||||
public:
|
||||
BuiltinTest() = default;
|
||||
~BuiltinTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_P(BuiltinTest, Parses) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto p = parser(params.input);
|
||||
|
||||
auto builtin = p.builtin_decoration();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto builtin = p->builtin_decoration();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(builtin, params.result);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsEof());
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
|
@ -60,11 +85,11 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
ast::Builtin::kGlobalInvocationId}));
|
||||
|
||||
TEST_F(ParserImplTest, BuiltinDecoration_NoMatch) {
|
||||
ParserImpl p{"not-a-builtin"};
|
||||
auto builtin = p.builtin_decoration();
|
||||
auto p = parser("not-a-builtin");
|
||||
auto builtin = p->builtin_decoration();
|
||||
ASSERT_EQ(builtin, ast::Builtin::kNone);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsIdentifier());
|
||||
EXPECT_EQ(t.to_str(), "not");
|
||||
}
|
||||
|
|
|
@ -14,54 +14,53 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, CaseBody_Empty) {
|
||||
ParserImpl p{""};
|
||||
auto e = p.case_body();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("");
|
||||
auto e = p->case_body();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
EXPECT_EQ(e.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, CaseBody_Statements) {
|
||||
ParserImpl p{R"(
|
||||
auto p = parser(R"(
|
||||
var a: i32;
|
||||
a = 2;)"};
|
||||
a = 2;)");
|
||||
|
||||
auto e = p.case_body();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto e = p->case_body();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.size(), 2);
|
||||
EXPECT_TRUE(e[0]->IsVariable());
|
||||
EXPECT_TRUE(e[1]->IsAssign());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, CaseBody_InvalidStatement) {
|
||||
ParserImpl p{"a ="};
|
||||
auto e = p.case_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a =");
|
||||
auto e = p->case_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(e.size(), 0);
|
||||
EXPECT_EQ(p.error(), "1:4: unable to parse right side of assignment");
|
||||
EXPECT_EQ(p->error(), "1:4: unable to parse right side of assignment");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, CaseBody_Fallthrough) {
|
||||
ParserImpl p{"fallthrough;"};
|
||||
auto e = p.case_body();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("fallthrough;");
|
||||
auto e = p->case_body();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.size(), 1);
|
||||
EXPECT_TRUE(e[0]->IsFallthrough());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, CaseBody_Fallthrough_MissingSemicolon) {
|
||||
ParserImpl p{"fallthrough"};
|
||||
auto e = p.case_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fallthrough");
|
||||
auto e = p->case_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(e.size(), 0);
|
||||
EXPECT_EQ(p.error(), "1:12: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:12: missing ;");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -19,17 +19,16 @@
|
|||
#include "src/ast/type/vector_type.h"
|
||||
#include "src/ast/type_initializer_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_TypeDecl) {
|
||||
ParserImpl p{"vec2<f32>(1., 2.)"};
|
||||
auto e = p.const_expr();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("vec2<f32>(1., 2.)");
|
||||
auto e = p->const_expr();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsInitializer());
|
||||
ASSERT_TRUE(e->AsInitializer()->IsTypeInitializer());
|
||||
|
@ -55,57 +54,57 @@ TEST_F(ParserImplTest, ConstExpr_TypeDecl) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingRightParen) {
|
||||
ParserImpl p{"vec2<f32>(1., 2."};
|
||||
auto e = p.const_expr();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec2<f32>(1., 2.");
|
||||
auto e = p->const_expr();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:17: missing ) for type initializer");
|
||||
EXPECT_EQ(p->error(), "1:17: missing ) for type initializer");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingLeftParen) {
|
||||
ParserImpl p{"vec2<f32> 1., 2.)"};
|
||||
auto e = p.const_expr();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec2<f32> 1., 2.)");
|
||||
auto e = p->const_expr();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing ( for type initializer");
|
||||
EXPECT_EQ(p->error(), "1:11: missing ( for type initializer");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_TypeDecl_HangingComma) {
|
||||
ParserImpl p{"vec2<f32>(1.,)"};
|
||||
auto e = p.const_expr();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec2<f32>(1.,)");
|
||||
auto e = p->const_expr();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: unable to parse const literal");
|
||||
EXPECT_EQ(p->error(), "1:14: unable to parse const literal");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingComma) {
|
||||
ParserImpl p{"vec2<f32>(1. 2."};
|
||||
auto e = p.const_expr();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec2<f32>(1. 2.");
|
||||
auto e = p->const_expr();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: missing ) for type initializer");
|
||||
EXPECT_EQ(p->error(), "1:14: missing ) for type initializer");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_MissingExpr) {
|
||||
ParserImpl p{"vec2<f32>()"};
|
||||
auto e = p.const_expr();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec2<f32>()");
|
||||
auto e = p->const_expr();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: unable to parse const literal");
|
||||
EXPECT_EQ(p->error(), "1:11: unable to parse const literal");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_InvalidExpr) {
|
||||
ParserImpl p{"vec2<f32>(1., if(a) {})"};
|
||||
auto e = p.const_expr();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec2<f32>(1., if(a) {})");
|
||||
auto e = p->const_expr();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: unable to parse const literal");
|
||||
EXPECT_EQ(p->error(), "1:15: unable to parse const literal");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_ConstLiteral) {
|
||||
ParserImpl p{"true"};
|
||||
auto e = p.const_expr();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("true");
|
||||
auto e = p->const_expr();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsInitializer());
|
||||
ASSERT_TRUE(e->AsInitializer()->IsConstInitializer());
|
||||
|
@ -115,11 +114,11 @@ TEST_F(ParserImplTest, ConstExpr_ConstLiteral) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_ConstLiteral_Invalid) {
|
||||
ParserImpl p{"invalid"};
|
||||
auto e = p.const_expr();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("invalid");
|
||||
auto e = p->const_expr();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:1: unknown type alias 'invalid'");
|
||||
EXPECT_EQ(p->error(), "1:1: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -18,68 +18,67 @@
|
|||
#include "src/ast/int_literal.h"
|
||||
#include "src/ast/uint_literal.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ConstLiteral_Int) {
|
||||
ParserImpl p{"-234"};
|
||||
auto c = p.const_literal();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("-234");
|
||||
auto c = p->const_literal();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_TRUE(c->IsInt());
|
||||
EXPECT_EQ(c->AsInt()->value(), -234);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstLiteral_Uint) {
|
||||
ParserImpl p{"234u"};
|
||||
auto c = p.const_literal();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("234u");
|
||||
auto c = p->const_literal();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_TRUE(c->IsUint());
|
||||
EXPECT_EQ(c->AsUint()->value(), 234u);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstLiteral_Float) {
|
||||
ParserImpl p{"234.e12"};
|
||||
auto c = p.const_literal();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("234.e12");
|
||||
auto c = p->const_literal();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_TRUE(c->IsFloat());
|
||||
EXPECT_FLOAT_EQ(c->AsFloat()->value(), 234e12);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstLiteral_InvalidFloat) {
|
||||
ParserImpl p{"1.2e+256"};
|
||||
auto c = p.const_literal();
|
||||
auto p = parser("1.2e+256");
|
||||
auto c = p->const_literal();
|
||||
ASSERT_EQ(c, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstLiteral_True) {
|
||||
ParserImpl p{"true"};
|
||||
auto c = p.const_literal();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("true");
|
||||
auto c = p->const_literal();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_TRUE(c->IsBool());
|
||||
EXPECT_TRUE(c->AsBool()->IsTrue());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstLiteral_False) {
|
||||
ParserImpl p{"false"};
|
||||
auto c = p.const_literal();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("false");
|
||||
auto c = p->const_literal();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_TRUE(c->IsBool());
|
||||
EXPECT_TRUE(c->AsBool()->IsFalse());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstLiteral_NoMatch) {
|
||||
ParserImpl p{"another-token"};
|
||||
auto c = p.const_literal();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("another-token");
|
||||
auto c = p->const_literal();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_EQ(c, nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,17 +17,16 @@
|
|||
#include "src/ast/return_statement.h"
|
||||
#include "src/ast/statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ContinueStmt) {
|
||||
ParserImpl p{"continue"};
|
||||
auto e = p.continue_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("continue");
|
||||
auto e = p->continue_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsContinue());
|
||||
EXPECT_EQ(e->condition(), ast::StatementCondition::kNone);
|
||||
|
@ -35,9 +34,9 @@ TEST_F(ParserImplTest, ContinueStmt) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ContinueStmt_WithIf) {
|
||||
ParserImpl p{"continue if (a == b)"};
|
||||
auto e = p.continue_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("continue if (a == b)");
|
||||
auto e = p->continue_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsContinue());
|
||||
EXPECT_EQ(e->condition(), ast::StatementCondition::kIf);
|
||||
|
@ -46,9 +45,9 @@ TEST_F(ParserImplTest, ContinueStmt_WithIf) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ContinueStmt_WithUnless) {
|
||||
ParserImpl p{"continue unless (a == b)"};
|
||||
auto e = p.continue_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("continue unless (a == b)");
|
||||
auto e = p->continue_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsContinue());
|
||||
EXPECT_EQ(e->condition(), ast::StatementCondition::kUnless);
|
||||
|
@ -57,19 +56,19 @@ TEST_F(ParserImplTest, ContinueStmt_WithUnless) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ContinueStmt_InvalidRHS) {
|
||||
ParserImpl p{"continue if (a = b)"};
|
||||
auto e = p.continue_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("continue if (a = b)");
|
||||
auto e = p->continue_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:16: expected )");
|
||||
EXPECT_EQ(p->error(), "1:16: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ContinueStmt_MissingRHS) {
|
||||
ParserImpl p{"continue if"};
|
||||
auto e = p.continue_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("continue if");
|
||||
auto e = p->continue_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: expected (");
|
||||
EXPECT_EQ(p->error(), "1:12: expected (");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -14,27 +14,26 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ContinuingStmt) {
|
||||
ParserImpl p{"continuing { nop; }"};
|
||||
auto e = p.continuing_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("continuing { nop; }");
|
||||
auto e = p->continuing_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.size(), 1);
|
||||
ASSERT_TRUE(e[0]->IsNop());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ContinuingStmt_InvalidBody) {
|
||||
ParserImpl p{"continuing { nop }"};
|
||||
auto e = p.continuing_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("continuing { nop }");
|
||||
auto e = p->continuing_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e.size(), 0);
|
||||
EXPECT_EQ(p.error(), "1:18: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:18: missing ;");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/derivative_modifier.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
namespace {
|
||||
|
||||
struct DerivativeModifierData {
|
||||
const char* input;
|
||||
|
@ -31,16 +31,42 @@ inline std::ostream& operator<<(std::ostream& out,
|
|||
out << std::string(data.input);
|
||||
return out;
|
||||
}
|
||||
using DerivativeModifierTest = testing::TestWithParam<DerivativeModifierData>;
|
||||
|
||||
class DerivativeModifierTest
|
||||
: public testing::TestWithParam<DerivativeModifierData> {
|
||||
public:
|
||||
DerivativeModifierTest() = default;
|
||||
~DerivativeModifierTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_P(DerivativeModifierTest, Parses) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto p = parser(params.input);
|
||||
|
||||
auto mod = p.derivative_modifier();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto mod = p->derivative_modifier();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(mod, params.result);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsEof());
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
|
@ -51,11 +77,11 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
DerivativeModifierData{"coarse", ast::DerivativeModifier::kCoarse}));
|
||||
|
||||
TEST_F(ParserImplTest, DerivativeModifier_NoMatch) {
|
||||
ParserImpl p{"not-a-modifier"};
|
||||
auto stage = p.derivative_modifier();
|
||||
auto p = parser("not-a-modifier");
|
||||
auto stage = p->derivative_modifier();
|
||||
ASSERT_EQ(stage, ast::DerivativeModifier::kNone);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsIdentifier());
|
||||
EXPECT_EQ(t.to_str(), "not");
|
||||
}
|
||||
|
|
|
@ -15,17 +15,16 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/else_statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ElseStmt) {
|
||||
ParserImpl p{"else { a = b; c = d; }"};
|
||||
auto e = p.else_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("else { a = b; c = d; }");
|
||||
auto e = p->else_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsElse());
|
||||
ASSERT_EQ(e->condition(), nullptr);
|
||||
|
@ -33,19 +32,19 @@ TEST_F(ParserImplTest, ElseStmt) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ElseStmt_InvalidBody) {
|
||||
ParserImpl p{"else { fn main() -> void {}}"};
|
||||
auto e = p.else_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("else { fn main() -> void {}}");
|
||||
auto e = p->else_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing }");
|
||||
EXPECT_EQ(p->error(), "1:8: missing }");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ElseStmt_MissingBody) {
|
||||
ParserImpl p{"else"};
|
||||
auto e = p.else_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("else");
|
||||
auto e = p->else_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing {");
|
||||
EXPECT_EQ(p->error(), "1:5: missing {");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,17 +15,16 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/else_statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ElseIfStmt) {
|
||||
ParserImpl p{"elseif (a == 4) { a = b; c = d; }"};
|
||||
auto e = p.elseif_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("elseif (a == 4) { a = b; c = d; }");
|
||||
auto e = p->elseif_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.size(), 1);
|
||||
|
||||
ASSERT_TRUE(e[0]->IsElse());
|
||||
|
@ -35,9 +34,9 @@ TEST_F(ParserImplTest, ElseIfStmt) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
|
||||
ParserImpl p{"elseif (a == 4) { a = b; c = d; } elseif(c) { d = 2; }"};
|
||||
auto e = p.elseif_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("elseif (a == 4) { a = b; c = d; } elseif(c) { d = 2; }");
|
||||
auto e = p->elseif_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.size(), 2);
|
||||
|
||||
ASSERT_TRUE(e[0]->IsElse());
|
||||
|
@ -52,17 +51,17 @@ TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ElseIfStmt_InvalidBody) {
|
||||
ParserImpl p{"elseif (true) { fn main() -> void {}}"};
|
||||
auto e = p.elseif_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:17: missing }");
|
||||
auto p = parser("elseif (true) { fn main() -> void {}}");
|
||||
auto e = p->elseif_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:17: missing }");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ElseIfStmt_MissingBody) {
|
||||
ParserImpl p{"elseif (true)"};
|
||||
auto e = p.elseif_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:14: missing {");
|
||||
auto p = parser("elseif (true)");
|
||||
auto e = p->elseif_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:14: missing {");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,105 +15,104 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_Parses) {
|
||||
ParserImpl p{"entry_point fragment = main"};
|
||||
auto e = p.entry_point_decl();
|
||||
auto p = parser("entry_point fragment = main");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(e->stage(), ast::PipelineStage::kFragment);
|
||||
EXPECT_EQ(e->name(), "main");
|
||||
EXPECT_EQ(e->function_name(), "main");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_ParsesWithStringName) {
|
||||
ParserImpl p{R"(entry_point vertex as "main" = vtx_main)"};
|
||||
auto e = p.entry_point_decl();
|
||||
auto p = parser(R"(entry_point vertex as "main" = vtx_main)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(e->stage(), ast::PipelineStage::kVertex);
|
||||
EXPECT_EQ(e->name(), "main");
|
||||
EXPECT_EQ(e->function_name(), "vtx_main");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_ParsesWithIdentName) {
|
||||
ParserImpl p{R"(entry_point vertex as main = vtx_main)"};
|
||||
auto e = p.entry_point_decl();
|
||||
auto p = parser(R"(entry_point vertex as main = vtx_main)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(e->stage(), ast::PipelineStage::kVertex);
|
||||
EXPECT_EQ(e->name(), "main");
|
||||
EXPECT_EQ(e->function_name(), "vtx_main");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_MissingFnName) {
|
||||
ParserImpl p{R"(entry_point vertex as main =)"};
|
||||
auto e = p.entry_point_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser(R"(entry_point vertex as main =)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:29: invalid function name for entry point");
|
||||
EXPECT_EQ(p->error(), "1:29: invalid function name for entry point");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_InvalidFnName) {
|
||||
ParserImpl p{R"(entry_point vertex as main = 123)"};
|
||||
auto e = p.entry_point_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser(R"(entry_point vertex as main = 123)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:30: invalid function name for entry point");
|
||||
EXPECT_EQ(p->error(), "1:30: invalid function name for entry point");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_MissingEqual) {
|
||||
ParserImpl p{R"(entry_point vertex as main vtx_main)"};
|
||||
auto e = p.entry_point_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser(R"(entry_point vertex as main vtx_main)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:28: missing = for entry point");
|
||||
EXPECT_EQ(p->error(), "1:28: missing = for entry point");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_MissingName) {
|
||||
ParserImpl p{R"(entry_point vertex as = vtx_main)"};
|
||||
auto e = p.entry_point_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser(R"(entry_point vertex as = vtx_main)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:23: invalid name for entry point");
|
||||
EXPECT_EQ(p->error(), "1:23: invalid name for entry point");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_InvalidName) {
|
||||
ParserImpl p{R"(entry_point vertex as 123 = vtx_main)"};
|
||||
auto e = p.entry_point_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser(R"(entry_point vertex as 123 = vtx_main)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:23: invalid name for entry point");
|
||||
EXPECT_EQ(p->error(), "1:23: invalid name for entry point");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_MissingStageWithIdent) {
|
||||
ParserImpl p{R"(entry_point as 123 = vtx_main)"};
|
||||
auto e = p.entry_point_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser(R"(entry_point as 123 = vtx_main)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: missing pipeline stage for entry point");
|
||||
EXPECT_EQ(p->error(), "1:13: missing pipeline stage for entry point");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_MissingStage) {
|
||||
ParserImpl p{R"(entry_point = vtx_main)"};
|
||||
auto e = p.entry_point_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser(R"(entry_point = vtx_main)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: missing pipeline stage for entry point");
|
||||
EXPECT_EQ(p->error(), "1:13: missing pipeline stage for entry point");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EntryPoint_InvalidStage) {
|
||||
ParserImpl p{R"(entry_point invalid = vtx_main)"};
|
||||
auto e = p.entry_point_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser(R"(entry_point invalid = vtx_main)");
|
||||
auto e = p->entry_point_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: missing pipeline stage for entry point");
|
||||
EXPECT_EQ(p->error(), "1:13: missing pipeline stage for entry point");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, EqualityExpression_Parses_Equal) {
|
||||
ParserImpl p{"a == true"};
|
||||
auto e = p.equality_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a == true");
|
||||
auto e = p->equality_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,9 +47,9 @@ TEST_F(ParserImplTest, EqualityExpression_Parses_Equal) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
|
||||
ParserImpl p{"a != true"};
|
||||
auto e = p.equality_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a != true");
|
||||
auto e = p->equality_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -70,24 +69,24 @@ TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, EqualityExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} == true"};
|
||||
auto e = p.equality_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} == true");
|
||||
auto e = p->equality_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EqualityExpression_InvalidRHS) {
|
||||
ParserImpl p{"true == if (a) {}"};
|
||||
auto e = p.equality_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true == if (a) {}");
|
||||
auto e = p->equality_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: unable to parse right side of == expression");
|
||||
EXPECT_EQ(p->error(), "1:9: unable to parse right side of == expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, EqualityExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.equality_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->equality_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ExclusiveOrExpression_Parses) {
|
||||
ParserImpl p{"a ^ true"};
|
||||
auto e = p.exclusive_or_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a ^ true");
|
||||
auto e = p->exclusive_or_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,24 +47,24 @@ TEST_F(ParserImplTest, ExclusiveOrExpression_Parses) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} ^ true"};
|
||||
auto e = p.exclusive_or_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} ^ true");
|
||||
auto e = p->exclusive_or_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidRHS) {
|
||||
ParserImpl p{"true ^ if (a) {}"};
|
||||
auto e = p.exclusive_or_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true ^ if (a) {}");
|
||||
auto e = p->exclusive_or_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: unable to parse right side of ^ expression");
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of ^ expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ExclusiveOrExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.exclusive_or_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->exclusive_or_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -16,17 +16,16 @@
|
|||
#include "src/ast/function.h"
|
||||
#include "src/ast/type/type.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, FunctionDecl) {
|
||||
ParserImpl p{"fn main(a : i32, b : f32) -> void { return; }"};
|
||||
auto f = p.function_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("fn main(a : i32, b : f32) -> void { return; }");
|
||||
auto f = p->function_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(f, nullptr);
|
||||
|
||||
EXPECT_EQ(f->name(), "main");
|
||||
|
@ -45,19 +44,19 @@ TEST_F(ParserImplTest, FunctionDecl) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionDecl_InvalidHeader) {
|
||||
ParserImpl p{"fn main() -> { }"};
|
||||
auto f = p.function_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn main() -> { }");
|
||||
auto f = p->function_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: unable to determine function return type");
|
||||
EXPECT_EQ(p->error(), "1:14: unable to determine function return type");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionDecl_InvalidBody) {
|
||||
ParserImpl p{"fn main() -> void { return }"};
|
||||
auto f = p.function_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn main() -> void { return }");
|
||||
auto f = p->function_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:28: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:28: missing ;");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -16,17 +16,16 @@
|
|||
#include "src/ast/function.h"
|
||||
#include "src/ast/type/type.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, FunctionHeader) {
|
||||
ParserImpl p{"fn main(a : i32, b: f32) -> void"};
|
||||
auto f = p.function_header();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("fn main(a : i32, b: f32) -> void");
|
||||
auto f = p->function_header();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(f, nullptr);
|
||||
|
||||
EXPECT_EQ(f->name(), "main");
|
||||
|
@ -37,67 +36,67 @@ TEST_F(ParserImplTest, FunctionHeader) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionHeader_MissingIdent) {
|
||||
ParserImpl p{"fn () ->"};
|
||||
auto f = p.function_header();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn () ->");
|
||||
auto f = p->function_header();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:4: missing identifier for function");
|
||||
EXPECT_EQ(p->error(), "1:4: missing identifier for function");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionHeader_InvalidIdent) {
|
||||
ParserImpl p{"fn 133main() -> i32"};
|
||||
auto f = p.function_header();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn 133main() -> i32");
|
||||
auto f = p->function_header();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:4: missing identifier for function");
|
||||
EXPECT_EQ(p->error(), "1:4: missing identifier for function");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionHeader_MissingParenLeft) {
|
||||
ParserImpl p{"fn main) -> i32"};
|
||||
auto f = p.function_header();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn main) -> i32");
|
||||
auto f = p->function_header();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing ( for function declaration");
|
||||
EXPECT_EQ(p->error(), "1:8: missing ( for function declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionHeader_InvalidParamList) {
|
||||
ParserImpl p{"fn main(a :i32,) -> i32"};
|
||||
auto f = p.function_header();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn main(a :i32,) -> i32");
|
||||
auto f = p->function_header();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: found , but no variable declaration");
|
||||
EXPECT_EQ(p->error(), "1:15: found , but no variable declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionHeader_MissingParenRight) {
|
||||
ParserImpl p{"fn main( -> i32"};
|
||||
auto f = p.function_header();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn main( -> i32");
|
||||
auto f = p->function_header();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: missing ) for function declaration");
|
||||
EXPECT_EQ(p->error(), "1:10: missing ) for function declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionHeader_MissingArrow) {
|
||||
ParserImpl p{"fn main() i32"};
|
||||
auto f = p.function_header();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn main() i32");
|
||||
auto f = p->function_header();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing -> for function declaration");
|
||||
EXPECT_EQ(p->error(), "1:11: missing -> for function declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionHeader_InvalidReturnType) {
|
||||
ParserImpl p{"fn main() -> invalid"};
|
||||
auto f = p.function_header();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn main() -> invalid");
|
||||
auto f = p->function_header();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: unknown type alias 'invalid'");
|
||||
EXPECT_EQ(p->error(), "1:14: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionHeader_MissingReturnType) {
|
||||
ParserImpl p{"fn main() ->"};
|
||||
auto f = p.function_header();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fn main() ->");
|
||||
auto f = p->function_header();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(f, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: unable to determine function return type");
|
||||
EXPECT_EQ(p->error(), "1:13: unable to determine function return type");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -19,45 +19,38 @@
|
|||
#include "src/ast/type/vector_type.h"
|
||||
#include "src/ast/type/void_type.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, FunctionTypeDecl_Void) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto v = tm->Get(std::make_unique<ast::type::VoidType>());
|
||||
auto v = tm()->Get(std::make_unique<ast::type::VoidType>());
|
||||
|
||||
ParserImpl p{"void"};
|
||||
auto e = p.function_type_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("void");
|
||||
auto e = p->function_type_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, v);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionTypeDecl_Type) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto f32 = tm->Get(std::make_unique<ast::type::F32Type>());
|
||||
auto vec2 = tm->Get(std::make_unique<ast::type::VectorType>(f32, 2));
|
||||
auto f32 = tm()->Get(std::make_unique<ast::type::F32Type>());
|
||||
auto vec2 = tm()->Get(std::make_unique<ast::type::VectorType>(f32, 2));
|
||||
|
||||
ParserImpl p{"vec2<f32>"};
|
||||
auto e = p.function_type_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("vec2<f32>");
|
||||
auto e = p->function_type_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, vec2);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, FunctionTypeDecl_InvalidType) {
|
||||
ParserImpl p{"vec2<invalid>"};
|
||||
auto e = p.function_type_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec2<invalid>");
|
||||
auto e = p->function_type_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: unknown type alias 'invalid'");
|
||||
EXPECT_EQ(p->error(), "1:6: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -16,17 +16,16 @@
|
|||
#include "src/ast/decorated_variable.h"
|
||||
#include "src/ast/variable_decoration.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDecl) {
|
||||
ParserImpl p{"const a : f32 = 1."};
|
||||
auto e = p.global_constant_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("const a : f32 = 1.");
|
||||
auto e = p->global_constant_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
EXPECT_TRUE(e->is_const());
|
||||
|
@ -39,35 +38,35 @@ TEST_F(ParserImplTest, GlobalConstantDecl) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) {
|
||||
ParserImpl p{"const a: f32 1."};
|
||||
auto e = p.global_constant_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("const a: f32 1.");
|
||||
auto e = p->global_constant_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: missing = for const declaration");
|
||||
EXPECT_EQ(p->error(), "1:14: missing = for const declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
|
||||
ParserImpl p{"const a: invalid = 1."};
|
||||
auto e = p.global_constant_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("const a: invalid = 1.");
|
||||
auto e = p->global_constant_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: unknown type alias 'invalid'");
|
||||
EXPECT_EQ(p->error(), "1:10: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
|
||||
ParserImpl p{"const a: f32 = if (a) {}"};
|
||||
auto e = p.global_constant_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("const a: f32 = if (a) {}");
|
||||
auto e = p->global_constant_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:16: unable to parse const literal");
|
||||
EXPECT_EQ(p->error(), "1:16: unable to parse const literal");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
|
||||
ParserImpl p{"const a: f32 ="};
|
||||
auto e = p.global_constant_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("const a: f32 =");
|
||||
auto e = p->global_constant_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: unable to parse const literal");
|
||||
EXPECT_EQ(p->error(), "1:15: unable to parse const literal");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -14,25 +14,24 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_Semicolon) {
|
||||
ParserImpl p(";");
|
||||
p.global_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser(";");
|
||||
p->global_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_Import) {
|
||||
ParserImpl p{R"(import "GLSL.std.430" as glsl;)"};
|
||||
p.global_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser(R"(import "GLSL.std.430" as glsl;)");
|
||||
p->global_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
|
||||
auto m = p.module();
|
||||
auto m = p->module();
|
||||
ASSERT_EQ(1, m.imports().size());
|
||||
|
||||
const auto& import = m.imports()[0];
|
||||
|
@ -41,27 +40,27 @@ TEST_F(ParserImplTest, GlobalDecl_Import) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_Import_Invalid) {
|
||||
ParserImpl p{R"(import as glsl;)"};
|
||||
p.global_decl();
|
||||
auto p = parser(R"(import as glsl;)");
|
||||
p->global_decl();
|
||||
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:8: missing path for import");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:8: missing path for import");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_Import_Invalid_MissingSemicolon) {
|
||||
ParserImpl p{R"(import "GLSL.std.430" as glsl)"};
|
||||
p.global_decl();
|
||||
auto p = parser(R"(import "GLSL.std.430" as glsl)");
|
||||
p->global_decl();
|
||||
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:30: missing ';' for import");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:30: missing ';' for import");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_GlobalVariable) {
|
||||
ParserImpl p{"var<out> a : vec2<i32> = vec2<i32>(1, 2);"};
|
||||
p.global_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("var<out> a : vec2<i32> = vec2<i32>(1, 2);");
|
||||
p->global_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
|
||||
auto m = p.module();
|
||||
auto m = p->module();
|
||||
ASSERT_EQ(m.global_variables().size(), 1);
|
||||
|
||||
auto v = m.global_variables()[0].get();
|
||||
|
@ -69,25 +68,25 @@ TEST_F(ParserImplTest, GlobalDecl_GlobalVariable) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Invalid) {
|
||||
ParserImpl p{"var<out> a : vec2<invalid>;"};
|
||||
p.global_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:19: unknown type alias 'invalid'");
|
||||
auto p = parser("var<out> a : vec2<invalid>;");
|
||||
p->global_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:19: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_MissingSemicolon) {
|
||||
ParserImpl p{"var<out> a : vec2<i32>"};
|
||||
p.global_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:23: missing ';' for variable declaration");
|
||||
auto p = parser("var<out> a : vec2<i32>");
|
||||
p->global_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:23: missing ';' for variable declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_GlobalConstant) {
|
||||
ParserImpl p{"const a : i32 = 2;"};
|
||||
p.global_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("const a : i32 = 2;");
|
||||
p->global_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
|
||||
auto m = p.module();
|
||||
auto m = p->module();
|
||||
ASSERT_EQ(m.global_variables().size(), 1);
|
||||
|
||||
auto v = m.global_variables()[0].get();
|
||||
|
@ -95,82 +94,82 @@ TEST_F(ParserImplTest, GlobalDecl_GlobalConstant) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_Invalid) {
|
||||
ParserImpl p{"const a : vec2<i32>;"};
|
||||
p.global_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:20: missing = for const declaration");
|
||||
auto p = parser("const a : vec2<i32>;");
|
||||
p->global_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:20: missing = for const declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_MissingSemicolon) {
|
||||
ParserImpl p{"const a : vec2<i32> = vec2<i32>(1, 2)"};
|
||||
p.global_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:38: missing ';' for constant declaration");
|
||||
auto p = parser("const a : vec2<i32> = vec2<i32>(1, 2)");
|
||||
p->global_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:38: missing ';' for constant declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_EntryPoint) {
|
||||
ParserImpl p{"entry_point vertex = main;"};
|
||||
p.global_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("entry_point vertex = main;");
|
||||
p->global_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
|
||||
auto m = p.module();
|
||||
auto m = p->module();
|
||||
ASSERT_EQ(m.entry_points().size(), 1);
|
||||
EXPECT_EQ(m.entry_points()[0]->name(), "main");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_EntryPoint_Invalid) {
|
||||
ParserImpl p{"entry_point main;"};
|
||||
p.global_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:13: missing pipeline stage for entry point");
|
||||
auto p = parser("entry_point main;");
|
||||
p->global_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:13: missing pipeline stage for entry point");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_EntryPoint_MissingSemicolon) {
|
||||
ParserImpl p{"entry_point vertex = main"};
|
||||
p.global_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:26: missing ';' for entry point");
|
||||
auto p = parser("entry_point vertex = main");
|
||||
p->global_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:26: missing ';' for entry point");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_TypeAlias) {
|
||||
ParserImpl p{"type A = i32;"};
|
||||
p.global_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("type A = i32;");
|
||||
p->global_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
|
||||
auto m = p.module();
|
||||
auto m = p->module();
|
||||
ASSERT_EQ(m.alias_types().size(), 1);
|
||||
EXPECT_EQ(m.alias_types()[0]->name(), "A");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_TypeAlias_Invalid) {
|
||||
ParserImpl p{"type A = invalid;"};
|
||||
p.global_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:10: unknown type alias 'invalid'");
|
||||
auto p = parser("type A = invalid;");
|
||||
p->global_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:10: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_TypeAlias_MissingSemicolon) {
|
||||
ParserImpl p{"type A = i32"};
|
||||
p.global_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:13: missing ';' for type alias");
|
||||
auto p = parser("type A = i32");
|
||||
p->global_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:13: missing ';' for type alias");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_Function) {
|
||||
ParserImpl p{"fn main() -> void { return; }"};
|
||||
p.global_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("fn main() -> void { return; }");
|
||||
p->global_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
|
||||
auto m = p.module();
|
||||
auto m = p->module();
|
||||
ASSERT_EQ(m.functions().size(), 1);
|
||||
EXPECT_EQ(m.functions()[0]->name(), "main");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalDecl_Function_Invalid) {
|
||||
ParserImpl p{"fn main() -> { return; }"};
|
||||
p.global_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:14: unable to determine function return type");
|
||||
auto p = parser("fn main() -> { return; }");
|
||||
p->global_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:14: unable to determine function return type");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -16,17 +16,16 @@
|
|||
#include "src/ast/decorated_variable.h"
|
||||
#include "src/ast/variable_decoration.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, GlobalVariableDecl_WithoutInitializer) {
|
||||
ParserImpl p{"var<out> a : f32"};
|
||||
auto e = p.global_variable_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("var<out> a : f32");
|
||||
auto e = p->global_variable_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
EXPECT_EQ(e->name(), "a");
|
||||
|
@ -38,9 +37,9 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithoutInitializer) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalVariableDecl_WithInitializer) {
|
||||
ParserImpl p{"var<out> a : f32 = 1."};
|
||||
auto e = p.global_variable_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("var<out> a : f32 = 1.");
|
||||
auto e = p->global_variable_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
EXPECT_EQ(e->name(), "a");
|
||||
|
@ -55,9 +54,9 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithInitializer) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) {
|
||||
ParserImpl p{"[[binding 2, set 1]] var<out> a : f32"};
|
||||
auto e = p.global_variable_decl();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("[[binding 2, set 1]] var<out> a : f32");
|
||||
auto e = p->global_variable_decl();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsDecorated());
|
||||
|
||||
|
@ -78,27 +77,27 @@ TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidDecoration) {
|
||||
ParserImpl p{"[[binding]] var<out> a : f32"};
|
||||
auto e = p.global_variable_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("[[binding]] var<out> a : f32");
|
||||
auto e = p->global_variable_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: invalid value for binding decoration");
|
||||
EXPECT_EQ(p->error(), "1:10: invalid value for binding decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidConstExpr) {
|
||||
ParserImpl p{"var<out> a : f32 = if (a) {}"};
|
||||
auto e = p.global_variable_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("var<out> a : f32 = if (a) {}");
|
||||
auto e = p->global_variable_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:20: unable to parse const literal");
|
||||
EXPECT_EQ(p->error(), "1:20: unable to parse const literal");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
|
||||
ParserImpl p{"var<invalid> a : f32;"};
|
||||
auto e = p.global_variable_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("var<invalid> a : f32;");
|
||||
auto e = p->global_variable_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: invalid storage class for variable decoration");
|
||||
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable decoration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -16,17 +16,16 @@
|
|||
#include "src/ast/else_statement.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt) {
|
||||
ParserImpl p{"if (a == 4) { a = b; c = d; }"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a == 4) { a = b; c = d; }");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsIf());
|
||||
|
@ -38,9 +37,9 @@ TEST_F(ParserImplTest, IfStmt) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt_WithElse) {
|
||||
ParserImpl p{"if (a == 4) { a = b; c = d; } elseif(c) { d = 2; } else {}"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a == 4) { a = b; c = d; } elseif(c) { d = 2; } else {}");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsIf());
|
||||
|
@ -58,16 +57,16 @@ TEST_F(ParserImplTest, IfStmt_WithElse) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt_WithPremerge) {
|
||||
ParserImpl p{R"(if (a == 4) {
|
||||
auto p = parser(R"(if (a == 4) {
|
||||
a = b;
|
||||
c = d;
|
||||
} else {
|
||||
d = 2;
|
||||
} premerge {
|
||||
a = 2;
|
||||
})"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
})");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsIf());
|
||||
|
@ -83,59 +82,59 @@ TEST_F(ParserImplTest, IfStmt_WithPremerge) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
|
||||
ParserImpl p{"if (a = 3) {}"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("if (a = 3) {}");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:7: expected )");
|
||||
EXPECT_EQ(p->error(), "1:7: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt_MissingCondition) {
|
||||
ParserImpl p{"if {}"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("if {}");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:4: expected (");
|
||||
EXPECT_EQ(p->error(), "1:4: expected (");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt_InvalidBody) {
|
||||
ParserImpl p{"if (a) { fn main() -> void {}}"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("if (a) { fn main() -> void {}}");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: missing }");
|
||||
EXPECT_EQ(p->error(), "1:10: missing }");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt_MissingBody) {
|
||||
ParserImpl p{"if (a)"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("if (a)");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:7: missing {");
|
||||
EXPECT_EQ(p->error(), "1:7: missing {");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
|
||||
ParserImpl p{"if (a) {} elseif (a) { fn main() -> a{}}"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("if (a) {} elseif (a) { fn main() -> a{}}");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:24: missing }");
|
||||
EXPECT_EQ(p->error(), "1:24: missing }");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt_InvalidElse) {
|
||||
ParserImpl p{"if (a) {} else { fn main() -> a{}}"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("if (a) {} else { fn main() -> a{}}");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:18: missing }");
|
||||
EXPECT_EQ(p->error(), "1:18: missing }");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, IfStmt_InvalidPremerge) {
|
||||
ParserImpl p{"if (a) {} else {} premerge { fn main() -> a{}}"};
|
||||
auto e = p.if_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("if (a) {} else {} premerge { fn main() -> a{}}");
|
||||
auto e = p->if_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:30: missing }");
|
||||
EXPECT_EQ(p->error(), "1:30: missing }");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -14,19 +14,18 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ImportDecl_Import) {
|
||||
ParserImpl p{R"(import "GLSL.std.450" as glsl)"};
|
||||
auto p = parser(R"(import "GLSL.std.450" as glsl)");
|
||||
|
||||
auto import = p.import_decl();
|
||||
auto import = p->import_decl();
|
||||
ASSERT_NE(import, nullptr);
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
|
||||
EXPECT_EQ("GLSL.std.450", import->path());
|
||||
EXPECT_EQ("glsl", import->name());
|
||||
|
@ -35,59 +34,59 @@ TEST_F(ParserImplTest, ImportDecl_Import) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ImportDecl_Import_WithNamespace) {
|
||||
ParserImpl p{R"(import "GLSL.std.450" as std::glsl)"};
|
||||
auto import = p.import_decl();
|
||||
auto p = parser(R"(import "GLSL.std.450" as std::glsl)");
|
||||
auto import = p->import_decl();
|
||||
ASSERT_NE(import, nullptr);
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
EXPECT_EQ("std::glsl", import->name());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ImportDecl_Invalid_MissingPath) {
|
||||
ParserImpl p{R"(import as glsl)"};
|
||||
auto import = p.import_decl();
|
||||
auto p = parser(R"(import as glsl)");
|
||||
auto import = p->import_decl();
|
||||
ASSERT_EQ(import, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:8: missing path for import");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:8: missing path for import");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ImportDecl_Invalid_EmptyPath) {
|
||||
ParserImpl p{R"(import "" as glsl)"};
|
||||
auto import = p.import_decl();
|
||||
auto p = parser(R"(import "" as glsl)");
|
||||
auto import = p->import_decl();
|
||||
ASSERT_EQ(import, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:8: import path must not be empty");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:8: import path must not be empty");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ImportDecl_Invalid_NameMissingTerminatingIdentifier) {
|
||||
ParserImpl p{R"(import "GLSL.std.450" as glsl::)"};
|
||||
auto import = p.import_decl();
|
||||
auto p = parser(R"(import "GLSL.std.450" as glsl::)");
|
||||
auto import = p->import_decl();
|
||||
ASSERT_EQ(import, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:32: invalid name for import");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:32: invalid name for import");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ImportDecl_Invalid_NameInvalid) {
|
||||
ParserImpl p{R"(import "GLSL.std.450" as 12glsl)"};
|
||||
auto import = p.import_decl();
|
||||
auto p = parser(R"(import "GLSL.std.450" as 12glsl)");
|
||||
auto import = p->import_decl();
|
||||
ASSERT_EQ(import, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:26: invalid name for import");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:26: invalid name for import");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ImportDecl_Invalid_MissingName) {
|
||||
ParserImpl p{R"(import "GLSL.std.450" as)"};
|
||||
auto import = p.import_decl();
|
||||
auto p = parser(R"(import "GLSL.std.450" as)");
|
||||
auto import = p->import_decl();
|
||||
ASSERT_EQ(import, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:25: missing name for import");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:25: missing name for import");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ImportDecl_Invalid_MissingAs) {
|
||||
ParserImpl p{R"(import "GLSL.std.450" glsl)"};
|
||||
auto import = p.import_decl();
|
||||
auto p = parser(R"(import "GLSL.std.450" glsl)");
|
||||
auto import = p->import_decl();
|
||||
ASSERT_EQ(import, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:23: missing 'as' for import");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:23: missing 'as' for import");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, InclusiveOrExpression_Parses) {
|
||||
ParserImpl p{"a | true"};
|
||||
auto e = p.inclusive_or_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a | true");
|
||||
auto e = p->inclusive_or_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,24 +47,24 @@ TEST_F(ParserImplTest, InclusiveOrExpression_Parses) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, InclusiveOrExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} | true"};
|
||||
auto e = p.inclusive_or_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} | true");
|
||||
auto e = p->inclusive_or_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, InclusiveOrExpression_InvalidRHS) {
|
||||
ParserImpl p{"true | if (a) {}"};
|
||||
auto e = p.inclusive_or_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true | if (a) {}");
|
||||
auto e = p->inclusive_or_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: unable to parse right side of | expression");
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of | expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, InclusiveOrExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.inclusive_or_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->inclusive_or_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, LogicalAndExpression_Parses) {
|
||||
ParserImpl p{"a && true"};
|
||||
auto e = p.logical_and_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a && true");
|
||||
auto e = p->logical_and_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,24 +47,24 @@ TEST_F(ParserImplTest, LogicalAndExpression_Parses) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, LogicalAndExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} && true"};
|
||||
auto e = p.logical_and_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} && true");
|
||||
auto e = p->logical_and_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, LogicalAndExpression_InvalidRHS) {
|
||||
ParserImpl p{"true && if (a) {}"};
|
||||
auto e = p.logical_and_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true && if (a) {}");
|
||||
auto e = p->logical_and_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: unable to parse right side of && expression");
|
||||
EXPECT_EQ(p->error(), "1:9: unable to parse right side of && expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, LogicalAndExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.logical_and_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->logical_and_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, LogicalOrExpression_Parses) {
|
||||
ParserImpl p{"a || true"};
|
||||
auto e = p.logical_or_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a || true");
|
||||
auto e = p->logical_or_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,24 +47,24 @@ TEST_F(ParserImplTest, LogicalOrExpression_Parses) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, LogicalOrExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} || true"};
|
||||
auto e = p.logical_or_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} || true");
|
||||
auto e = p->logical_or_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, LogicalOrExpression_InvalidRHS) {
|
||||
ParserImpl p{"true || if (a) {}"};
|
||||
auto e = p.logical_or_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true || if (a) {}");
|
||||
auto e = p->logical_or_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: unable to parse right side of || expression");
|
||||
EXPECT_EQ(p->error(), "1:9: unable to parse right side of || expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, LogicalOrExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.logical_or_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->logical_or_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -14,17 +14,16 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, LoopStmt_BodyNoContinuing) {
|
||||
ParserImpl p{"loop { nop; }"};
|
||||
auto e = p.loop_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("loop { nop; }");
|
||||
auto e = p->loop_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_EQ(e->body().size(), 1);
|
||||
|
@ -34,9 +33,9 @@ TEST_F(ParserImplTest, LoopStmt_BodyNoContinuing) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
|
||||
ParserImpl p{"loop { nop; continuing { kill; }}"};
|
||||
auto e = p.loop_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("loop { nop; continuing { kill; }}");
|
||||
auto e = p->loop_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_EQ(e->body().size(), 1);
|
||||
|
@ -47,18 +46,18 @@ TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, LoopStmt_NoBodyNoContinuing) {
|
||||
ParserImpl p{"loop { }"};
|
||||
auto e = p.loop_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("loop { }");
|
||||
auto e = p->loop_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_EQ(e->body().size(), 0);
|
||||
ASSERT_EQ(e->continuing().size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
|
||||
ParserImpl p{"loop { continuing { kill; }}"};
|
||||
auto e = p.loop_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("loop { continuing { kill; }}");
|
||||
auto e = p->loop_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_EQ(e->body().size(), 0);
|
||||
ASSERT_EQ(e->continuing().size(), 1);
|
||||
|
@ -66,35 +65,35 @@ TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, LoopStmt_MissingBracketLeft) {
|
||||
ParserImpl p{"loop kill; }"};
|
||||
auto e = p.loop_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("loop kill; }");
|
||||
auto e = p->loop_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing { for loop");
|
||||
EXPECT_EQ(p->error(), "1:6: missing { for loop");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, LoopStmt_MissingBracketRight) {
|
||||
ParserImpl p{"loop { kill; "};
|
||||
auto e = p.loop_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("loop { kill; ");
|
||||
auto e = p->loop_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: missing } for loop");
|
||||
EXPECT_EQ(p->error(), "1:14: missing } for loop");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, LoopStmt_InvalidStatements) {
|
||||
ParserImpl p{"loop { kill }"};
|
||||
auto e = p.loop_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("loop { kill }");
|
||||
auto e = p->loop_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:13: missing ;");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, LoopStmt_InvalidContinuing) {
|
||||
ParserImpl p{"loop { continuing { kill }}"};
|
||||
auto e = p.loop_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("loop { continuing { kill }}");
|
||||
auto e = p->loop_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:26: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:26: missing ;");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
||||
ParserImpl p{"a * true"};
|
||||
auto e = p.multiplicative_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a * true");
|
||||
auto e = p->multiplicative_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,9 +47,9 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
|
||||
ParserImpl p{"a / true"};
|
||||
auto e = p.multiplicative_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a / true");
|
||||
auto e = p->multiplicative_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -70,9 +69,9 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
|
||||
ParserImpl p{"a % true"};
|
||||
auto e = p.multiplicative_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a % true");
|
||||
auto e = p->multiplicative_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -92,24 +91,24 @@ TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} * true"};
|
||||
auto e = p.multiplicative_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} * true");
|
||||
auto e = p->multiplicative_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidRHS) {
|
||||
ParserImpl p{"true * if (a) {}"};
|
||||
auto e = p.multiplicative_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true * if (a) {}");
|
||||
auto e = p->multiplicative_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: unable to parse right side of * expression");
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of * expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, MultiplicativeExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.multiplicative_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->multiplicative_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -20,38 +20,33 @@
|
|||
#include "src/ast/type/vector_type.h"
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ParamList_Single) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto i32 = tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto i32 = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||
|
||||
ParserImpl p{"a : i32"};
|
||||
auto e = p.param_list();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a : i32");
|
||||
auto e = p->param_list();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
EXPECT_EQ(e.size(), 1);
|
||||
|
||||
EXPECT_EQ(e[0]->name(), "a");
|
||||
EXPECT_EQ(e[0]->type(), i32);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ParamList_Multiple) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto i32 = tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto f32 = tm->Get(std::make_unique<ast::type::F32Type>());
|
||||
auto vec2 = tm->Get(std::make_unique<ast::type::VectorType>(f32, 2));
|
||||
auto i32 = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto f32 = tm()->Get(std::make_unique<ast::type::F32Type>());
|
||||
auto vec2 = tm()->Get(std::make_unique<ast::type::VectorType>(f32, 2));
|
||||
|
||||
ParserImpl p{"a : i32, b: f32, c: vec2<f32>"};
|
||||
auto e = p.param_list();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a : i32, b: f32, c: vec2<f32>");
|
||||
auto e = p->param_list();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
EXPECT_EQ(e.size(), 3);
|
||||
|
||||
EXPECT_EQ(e[0]->name(), "a");
|
||||
|
@ -62,22 +57,20 @@ TEST_F(ParserImplTest, ParamList_Multiple) {
|
|||
|
||||
EXPECT_EQ(e[2]->name(), "c");
|
||||
EXPECT_EQ(e[2]->type(), vec2);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ParamList_Empty) {
|
||||
ParserImpl p{""};
|
||||
auto e = p.param_list();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("");
|
||||
auto e = p->param_list();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
EXPECT_EQ(e.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ParamList_HangingComma) {
|
||||
ParserImpl p{"a : i32,"};
|
||||
auto e = p.param_list();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:8: found , but no variable declaration");
|
||||
auto p = parser("a : i32,");
|
||||
auto e = p->param_list();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:8: found , but no variable declaration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -14,51 +14,50 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ParenRhsStmt) {
|
||||
ParserImpl p{"(a + b)"};
|
||||
auto e = p.paren_rhs_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("(a + b)");
|
||||
auto e = p->paren_rhs_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ParenRhsStmt_MissingLeftParen) {
|
||||
ParserImpl p{"true)"};
|
||||
auto e = p.paren_rhs_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true)");
|
||||
auto e = p->paren_rhs_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:1: expected (");
|
||||
EXPECT_EQ(p->error(), "1:1: expected (");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ParenRhsStmt_MissingRightParen) {
|
||||
ParserImpl p{"(true"};
|
||||
auto e = p.paren_rhs_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("(true");
|
||||
auto e = p->paren_rhs_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: expected )");
|
||||
EXPECT_EQ(p->error(), "1:6: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ParenRhsStmt_InvalidExpression) {
|
||||
ParserImpl p{"(if (a() {})"};
|
||||
auto e = p.paren_rhs_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("(if (a() {})");
|
||||
auto e = p->paren_rhs_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:2: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ParenRhsStmt_MissingExpression) {
|
||||
ParserImpl p{"()"};
|
||||
auto e = p.paren_rhs_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("()");
|
||||
auto e = p->paren_rhs_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:2: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/pipeline_stage.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
namespace {
|
||||
|
||||
struct PipelineStageData {
|
||||
const char* input;
|
||||
|
@ -30,16 +30,41 @@ inline std::ostream& operator<<(std::ostream& out, PipelineStageData data) {
|
|||
out << std::string(data.input);
|
||||
return out;
|
||||
}
|
||||
using PipelineStageTest = testing::TestWithParam<PipelineStageData>;
|
||||
|
||||
class PipelineStageTest : public testing::TestWithParam<PipelineStageData> {
|
||||
public:
|
||||
PipelineStageTest() = default;
|
||||
~PipelineStageTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_P(PipelineStageTest, Parses) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto p = parser(params.input);
|
||||
|
||||
auto stage = p.pipeline_stage();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto stage = p->pipeline_stage();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(stage, params.result);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsEof());
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
|
@ -51,11 +76,11 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
PipelineStageData{"compute", ast::PipelineStage::kCompute}));
|
||||
|
||||
TEST_F(ParserImplTest, PipelineStage_NoMatch) {
|
||||
ParserImpl p{"not-a-stage"};
|
||||
auto stage = p.pipeline_stage();
|
||||
auto p = parser("not-a-stage");
|
||||
auto stage = p->pipeline_stage();
|
||||
ASSERT_EQ(stage, ast::PipelineStage::kNone);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsIdentifier());
|
||||
EXPECT_EQ(t.to_str(), "not");
|
||||
}
|
||||
|
|
|
@ -23,17 +23,16 @@
|
|||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Array_ConstantIndex) {
|
||||
ParserImpl p{"a[1]"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a[1]");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsArrayAccessor());
|
||||
|
@ -52,9 +51,9 @@ TEST_F(ParserImplTest, PostfixExpression_Array_ConstantIndex) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Array_ExpressionIndex) {
|
||||
ParserImpl p{"a[1 + b / 4]"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a[1 + b / 4]");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsArrayAccessor());
|
||||
|
@ -69,33 +68,33 @@ TEST_F(ParserImplTest, PostfixExpression_Array_ExpressionIndex) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Array_MissingIndex) {
|
||||
ParserImpl p{"a[]"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a[]");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:3: unable to parse expression inside []");
|
||||
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Array_MissingRightBrace) {
|
||||
ParserImpl p{"a[1"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a[1");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:4: missing ] for array accessor");
|
||||
EXPECT_EQ(p->error(), "1:4: missing ] for array accessor");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Array_InvalidIndex) {
|
||||
ParserImpl p{"a[if(a() {})]"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a[if(a() {})]");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:3: unable to parse expression inside []");
|
||||
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Call_Empty) {
|
||||
ParserImpl p{"a()"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a()");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsCall());
|
||||
|
@ -110,9 +109,9 @@ TEST_F(ParserImplTest, PostfixExpression_Call_Empty) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Call_WithArgs) {
|
||||
ParserImpl p{"std::test(1, b, 2 + 3 / b)"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("std::test(1, b, 2 + 3 / b)");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsCall());
|
||||
|
@ -131,33 +130,33 @@ TEST_F(ParserImplTest, PostfixExpression_Call_WithArgs) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Call_InvalidArg) {
|
||||
ParserImpl p{"a(if(a) {})"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a(if(a) {})");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:3: unable to parse argument expression");
|
||||
EXPECT_EQ(p->error(), "1:3: unable to parse argument expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Call_HangingComma) {
|
||||
ParserImpl p{"a(b, )"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a(b, )");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: unable to parse argument expression after comma");
|
||||
EXPECT_EQ(p->error(), "1:6: unable to parse argument expression after comma");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_Call_MissingRightParen) {
|
||||
ParserImpl p{"a("};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a(");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:3: missing ) for call expression");
|
||||
EXPECT_EQ(p->error(), "1:3: missing ) for call expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_MemberAccessor) {
|
||||
ParserImpl p{"a.b"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a.b");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsMemberAccessor());
|
||||
|
||||
|
@ -172,25 +171,25 @@ TEST_F(ParserImplTest, PostfixExpression_MemberAccessor) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_MemberAccesssor_InvalidIdent) {
|
||||
ParserImpl p{"a.if"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a.if");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:3: missing identifier for member accessor");
|
||||
EXPECT_EQ(p->error(), "1:3: missing identifier for member accessor");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_MemberAccessor_MissingIdent) {
|
||||
ParserImpl p{"a."};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a.");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:3: missing identifier for member accessor");
|
||||
EXPECT_EQ(p->error(), "1:3: missing identifier for member accessor");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PostfixExpression_NonMatch_returnLHS) {
|
||||
ParserImpl p{"a b"};
|
||||
auto e = p.postfix_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a b");
|
||||
auto e = p->postfix_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -14,27 +14,26 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, PremergeStmt) {
|
||||
ParserImpl p{"premerge { nop; }"};
|
||||
auto e = p.premerge_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("premerge { nop; }");
|
||||
auto e = p->premerge_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.size(), 1);
|
||||
ASSERT_TRUE(e[0]->IsNop());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PremergeStmt_InvalidBody) {
|
||||
ParserImpl p{"premerge { nop }"};
|
||||
auto e = p.premerge_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("premerge { nop }");
|
||||
auto e = p->premerge_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e.size(), 0);
|
||||
EXPECT_EQ(p.error(), "1:16: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:16: missing ;");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -27,18 +27,17 @@
|
|||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Ident) {
|
||||
ParserImpl p{"a"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
auto ident = e->AsIdentifier();
|
||||
|
@ -47,9 +46,9 @@ TEST_F(ParserImplTest, PrimaryExpression_Ident) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Ident_WithNamespace) {
|
||||
ParserImpl p{"a::b::c::d"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a::b::c::d");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
auto ident = e->AsIdentifier();
|
||||
|
@ -61,17 +60,17 @@ TEST_F(ParserImplTest, PrimaryExpression_Ident_WithNamespace) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Ident_MissingIdent) {
|
||||
ParserImpl p{"a::"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a::");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:4: identifier expected");
|
||||
EXPECT_EQ(p->error(), "1:4: identifier expected");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
|
||||
ParserImpl p{"vec4<i32>(1, 2, 3, 4))"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("vec4<i32>(1, 2, 3, 4))");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsInitializer());
|
||||
ASSERT_TRUE(e->AsInitializer()->IsTypeInitializer());
|
||||
|
@ -105,41 +104,41 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
|
||||
ParserImpl p{"vec4<if>(2., 3., 4., 5.)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec4<if>(2., 3., 4., 5.)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: unable to determine subtype for vector");
|
||||
EXPECT_EQ(p->error(), "1:6: unable to determine subtype for vector");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_MissingLeftParen) {
|
||||
ParserImpl p{"vec4<f32> 2., 3., 4., 5.)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec4<f32> 2., 3., 4., 5.)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing ( for type initializer");
|
||||
EXPECT_EQ(p->error(), "1:11: missing ( for type initializer");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_MissingRightParen) {
|
||||
ParserImpl p{"vec4<f32>(2., 3., 4., 5."};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("vec4<f32>(2., 3., 4., 5.");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:25: missing ) for type initializer");
|
||||
EXPECT_EQ(p->error(), "1:25: missing ) for type initializer");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidValue) {
|
||||
ParserImpl p{"i32(if(a) {})"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("i32(if(a) {})");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: unable to parse argument expression");
|
||||
EXPECT_EQ(p->error(), "1:5: unable to parse argument expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
|
||||
ParserImpl p{"true"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("true");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsInitializer());
|
||||
ASSERT_TRUE(e->AsInitializer()->IsConstInitializer());
|
||||
|
@ -149,44 +148,43 @@ TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr) {
|
||||
ParserImpl p{"(a == b)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("(a == b)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_MissingRightParen) {
|
||||
ParserImpl p{"(a == b"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("(a == b");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: expected )");
|
||||
EXPECT_EQ(p->error(), "1:8: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_MissingExpr) {
|
||||
ParserImpl p{"()"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("()");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:2: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_InvalidExpr) {
|
||||
ParserImpl p{"(if (a) {})"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("(if (a) {})");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:2: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Cast) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto f32_type = tm->Get(std::make_unique<ast::type::F32Type>());
|
||||
auto f32_type = tm()->Get(std::make_unique<ast::type::F32Type>());
|
||||
|
||||
ParserImpl p{"cast<f32>(1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("cast<f32>(1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsCast());
|
||||
|
||||
|
@ -195,73 +193,70 @@ TEST_F(ParserImplTest, PrimaryExpression_Cast) {
|
|||
|
||||
ASSERT_TRUE(c->expr()->IsInitializer());
|
||||
ASSERT_TRUE(c->expr()->AsInitializer()->IsConstInitializer());
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingGreaterThan) {
|
||||
ParserImpl p{"cast<f32(1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("cast<f32(1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: missing > for cast expression");
|
||||
EXPECT_EQ(p->error(), "1:9: missing > for cast expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingType) {
|
||||
ParserImpl p{"cast<>(1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("cast<>(1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing type for cast expression");
|
||||
EXPECT_EQ(p->error(), "1:6: missing type for cast expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_InvalidType) {
|
||||
ParserImpl p{"cast<invalid>(1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("cast<invalid>(1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: unknown type alias 'invalid'");
|
||||
EXPECT_EQ(p->error(), "1:6: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingLeftParen) {
|
||||
ParserImpl p{"cast<f32>1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("cast<f32>1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: expected (");
|
||||
EXPECT_EQ(p->error(), "1:10: expected (");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingRightParen) {
|
||||
ParserImpl p{"cast<f32>(1"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("cast<f32>(1");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: expected )");
|
||||
EXPECT_EQ(p->error(), "1:12: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_MissingExpression) {
|
||||
ParserImpl p{"cast<f32>()"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("cast<f32>()");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:11: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_Cast_InvalidExpression) {
|
||||
ParserImpl p{"cast<f32>(if (a) {})"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("cast<f32>(if (a) {})");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:11: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_As) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto f32_type = tm->Get(std::make_unique<ast::type::F32Type>());
|
||||
auto f32_type = tm()->Get(std::make_unique<ast::type::F32Type>());
|
||||
|
||||
ParserImpl p{"as<f32>(1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("as<f32>(1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsAs());
|
||||
|
||||
|
@ -270,64 +265,62 @@ TEST_F(ParserImplTest, PrimaryExpression_As) {
|
|||
|
||||
ASSERT_TRUE(c->expr()->IsInitializer());
|
||||
ASSERT_TRUE(c->expr()->AsInitializer()->IsConstInitializer());
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_As_MissingGreaterThan) {
|
||||
ParserImpl p{"as<f32(1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("as<f32(1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:7: missing > for as expression");
|
||||
EXPECT_EQ(p->error(), "1:7: missing > for as expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_As_MissingType) {
|
||||
ParserImpl p{"as<>(1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("as<>(1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:4: missing type for as expression");
|
||||
EXPECT_EQ(p->error(), "1:4: missing type for as expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_As_InvalidType) {
|
||||
ParserImpl p{"as<invalid>(1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("as<invalid>(1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:4: unknown type alias 'invalid'");
|
||||
EXPECT_EQ(p->error(), "1:4: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_As_MissingLeftParen) {
|
||||
ParserImpl p{"as<f32>1)"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("as<f32>1)");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: expected (");
|
||||
EXPECT_EQ(p->error(), "1:8: expected (");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_As_MissingRightParen) {
|
||||
ParserImpl p{"as<f32>(1"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("as<f32>(1");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: expected )");
|
||||
EXPECT_EQ(p->error(), "1:10: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_As_MissingExpression) {
|
||||
ParserImpl p{"as<f32>()"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("as<f32>()");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:9: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_As_InvalidExpression) {
|
||||
ParserImpl p{"as<f32>(if (a) {})"};
|
||||
auto e = p.primary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("as<f32>(if (a) {})");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:9: unable to parse expression");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -14,17 +14,16 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, RegardlessStmt) {
|
||||
ParserImpl p{"regardless (a) { kill; }"};
|
||||
auto e = p.regardless_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("regardless (a) { kill; }");
|
||||
auto e = p->regardless_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsRegardless());
|
||||
ASSERT_NE(e->condition(), nullptr);
|
||||
|
@ -34,27 +33,27 @@ TEST_F(ParserImplTest, RegardlessStmt) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, RegardlessStmt_InvalidCondition) {
|
||||
ParserImpl p{"regardless(if(a){}) {}"};
|
||||
auto e = p.regardless_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("regardless(if(a){}) {}");
|
||||
auto e = p->regardless_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:12: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, RegardlessStmt_EmptyCondition) {
|
||||
ParserImpl p{"regardless() {}"};
|
||||
auto e = p.regardless_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("regardless() {}");
|
||||
auto e = p->regardless_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:12: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, RegardlessStmt_InvalidBody) {
|
||||
ParserImpl p{"regardless(a + 2 - 5 == true) { kill }"};
|
||||
auto e = p.regardless_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("regardless(a + 2 - 5 == true) { kill }");
|
||||
auto e = p->regardless_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:38: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:38: missing ;");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThan) {
|
||||
ParserImpl p{"a < true"};
|
||||
auto e = p.relational_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a < true");
|
||||
auto e = p->relational_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,9 +47,9 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_LessThan) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
|
||||
ParserImpl p{"a > true"};
|
||||
auto e = p.relational_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a > true");
|
||||
auto e = p->relational_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -70,9 +69,9 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
|
||||
ParserImpl p{"a <= true"};
|
||||
auto e = p.relational_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a <= true");
|
||||
auto e = p->relational_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -92,9 +91,9 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
|
||||
ParserImpl p{"a >= true"};
|
||||
auto e = p.relational_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a >= true");
|
||||
auto e = p->relational_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -114,24 +113,24 @@ TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, RelationalExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} < true"};
|
||||
auto e = p.relational_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} < true");
|
||||
auto e = p->relational_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, RelationalExpression_InvalidRHS) {
|
||||
ParserImpl p{"true < if (a) {}"};
|
||||
auto e = p.relational_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true < if (a) {}");
|
||||
auto e = p->relational_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: unable to parse right side of < expression");
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse right side of < expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, RelationalExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.relational_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->relational_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/relational_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftLeft) {
|
||||
ParserImpl p{"a << true"};
|
||||
auto e = p.shift_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a << true");
|
||||
auto e = p->shift_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -48,9 +47,9 @@ TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftLeft) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) {
|
||||
ParserImpl p{"a >> true"};
|
||||
auto e = p.shift_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a >> true");
|
||||
auto e = p->shift_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -70,9 +69,9 @@ TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRightArith) {
|
||||
ParserImpl p{"a >>> true"};
|
||||
auto e = p.shift_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a >>> true");
|
||||
auto e = p->shift_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsRelational());
|
||||
|
@ -92,24 +91,24 @@ TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRightArith) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, ShiftExpression_InvalidLHS) {
|
||||
ParserImpl p{"if (a) {} << true"};
|
||||
auto e = p.shift_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {} << true");
|
||||
auto e = p->shift_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ShiftExpression_InvalidRHS) {
|
||||
ParserImpl p{"true << if (a) {}"};
|
||||
auto e = p.shift_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("true << if (a) {}");
|
||||
auto e = p->shift_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: unable to parse right side of << expression");
|
||||
EXPECT_EQ(p->error(), "1:9: unable to parse right side of << expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ShiftExpression_NoOr_ReturnsLHS) {
|
||||
ParserImpl p{"a true"};
|
||||
auto e = p.shift_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a true");
|
||||
auto e = p->shift_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIdentifier());
|
||||
}
|
||||
|
|
|
@ -16,32 +16,31 @@
|
|||
#include "src/ast/return_statement.h"
|
||||
#include "src/ast/statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, Statement) {
|
||||
ParserImpl p{"return;"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("return;");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
EXPECT_TRUE(e->IsReturn());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Semicolon) {
|
||||
ParserImpl p{";"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser(";");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Return_NoValue) {
|
||||
ParserImpl p{"return;"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("return;");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsReturn());
|
||||
|
@ -50,9 +49,9 @@ TEST_F(ParserImplTest, Statement_Return_NoValue) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Return_Value) {
|
||||
ParserImpl p{"return a + b * (.1 - .2);"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("return a + b * (.1 - .2);");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsReturn());
|
||||
|
@ -62,227 +61,227 @@ TEST_F(ParserImplTest, Statement_Return_Value) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Return_MissingSemi) {
|
||||
ParserImpl p{"return"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("return");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:7: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:7: missing ;");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Return_Invalid) {
|
||||
ParserImpl p{"return if(a) {};"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("return if(a) {};");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:8: missing ;");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_If) {
|
||||
ParserImpl p{"if (a) {}"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("if (a) {}");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsIf());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_If_Invalid) {
|
||||
ParserImpl p{"if (a) { fn main() -> {}}"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("if (a) { fn main() -> {}}");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: missing }");
|
||||
EXPECT_EQ(p->error(), "1:10: missing }");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Unless) {
|
||||
ParserImpl p{"unless (a) {}"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("unless (a) {}");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnless());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Unless_Invalid) {
|
||||
ParserImpl p{"unless () {}"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("unless () {}");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:9: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Regardless) {
|
||||
ParserImpl p{"regardless (a) {}"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("regardless (a) {}");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsRegardless());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Regardless_Invalid) {
|
||||
ParserImpl p{"regardless () {}"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("regardless () {}");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:13: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Variable) {
|
||||
ParserImpl p{"var a : i32 = 1;"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("var a : i32 = 1;");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsVariable());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Variable_Invalid) {
|
||||
ParserImpl p{"var a : i32 =;"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("var a : i32 =;");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: missing initializer for variable declaration");
|
||||
EXPECT_EQ(p->error(), "1:14: missing initializer for variable declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Variable_MissingSemicolon) {
|
||||
ParserImpl p{"var a : i32"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("var a : i32");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:12: missing ;");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Switch) {
|
||||
ParserImpl p{"switch (a) {}"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("switch (a) {}");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsSwitch());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Switch_Invalid) {
|
||||
ParserImpl p{"switch (a) { case: {}}"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("switch (a) { case: {}}");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:18: unable to parse case conditional");
|
||||
EXPECT_EQ(p->error(), "1:18: unable to parse case conditional");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Loop) {
|
||||
ParserImpl p{"loop {}"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("loop {}");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsLoop());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Loop_Invalid) {
|
||||
ParserImpl p{"loop kill; }"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("loop kill; }");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing { for loop");
|
||||
EXPECT_EQ(p->error(), "1:6: missing { for loop");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Assignment) {
|
||||
ParserImpl p{"a = b;"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a = b;");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
EXPECT_TRUE(e->IsAssign());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Assignment_Invalid) {
|
||||
ParserImpl p{"a = if(b) {};"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a = if(b) {};");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: unable to parse right side of assignment");
|
||||
EXPECT_EQ(p->error(), "1:5: unable to parse right side of assignment");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Assignment_MissingSemicolon) {
|
||||
ParserImpl p{"a = b"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a = b");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:6: missing ;");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Break) {
|
||||
ParserImpl p{"break;"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("break;");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
EXPECT_TRUE(e->IsBreak());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Break_Invalid) {
|
||||
ParserImpl p{"break if (a = b);"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("break if (a = b);");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: expected )");
|
||||
EXPECT_EQ(p->error(), "1:13: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Break_MissingSemicolon) {
|
||||
ParserImpl p{"break if (a == b)"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("break if (a == b)");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:18: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:18: missing ;");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Continue) {
|
||||
ParserImpl p{"continue;"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("continue;");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
EXPECT_TRUE(e->IsContinue());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Continue_Invalid) {
|
||||
ParserImpl p{"continue if (a = b);"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("continue if (a = b);");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:16: expected )");
|
||||
EXPECT_EQ(p->error(), "1:16: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Continue_MissingSemicolon) {
|
||||
ParserImpl p{"continue if (a == b)"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("continue if (a == b)");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:21: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:21: missing ;");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Kill) {
|
||||
ParserImpl p{"kill;"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("kill;");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
EXPECT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsKill());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Kill_MissingSemicolon) {
|
||||
ParserImpl p{"kill"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("kill");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:5: missing ;");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Nop) {
|
||||
ParserImpl p{"nop;"};
|
||||
auto e = p.statement();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("nop;");
|
||||
auto e = p->statement();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
EXPECT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsNop());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statement_Nop_MissingSemicolon) {
|
||||
ParserImpl p{"nop"};
|
||||
auto e = p.statement();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("nop");
|
||||
auto e = p->statement();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:4: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:4: missing ;");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,17 +15,16 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, Statements) {
|
||||
ParserImpl p{"nop; kill; return;"};
|
||||
auto e = p.statements();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("nop; kill; return;");
|
||||
auto e = p->statements();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.size(), 3);
|
||||
EXPECT_TRUE(e[0]->IsNop());
|
||||
EXPECT_TRUE(e[1]->IsKill());
|
||||
|
@ -33,9 +32,9 @@ TEST_F(ParserImplTest, Statements) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, Statements_Empty) {
|
||||
ParserImpl p{""};
|
||||
auto e = p.statements();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("");
|
||||
auto e = p->statements();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_EQ(e.size(), 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/storage_class.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
namespace {
|
||||
|
||||
struct StorageClassData {
|
||||
const char* input;
|
||||
|
@ -30,16 +30,41 @@ inline std::ostream& operator<<(std::ostream& out, StorageClassData data) {
|
|||
out << std::string(data.input);
|
||||
return out;
|
||||
}
|
||||
using StorageClassTest = testing::TestWithParam<StorageClassData>;
|
||||
|
||||
class StorageClassTest : public testing::TestWithParam<StorageClassData> {
|
||||
public:
|
||||
StorageClassTest() = default;
|
||||
~StorageClassTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_P(StorageClassTest, Parses) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto p = parser(params.input);
|
||||
|
||||
auto sc = p.storage_class();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto sc = p->storage_class();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(sc, params.result);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsEof());
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
|
@ -59,11 +84,11 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
StorageClassData{"function", ast::StorageClass::kFunction}));
|
||||
|
||||
TEST_F(ParserImplTest, StorageClass_NoMatch) {
|
||||
ParserImpl p{"not-a-storage-class"};
|
||||
auto sc = p.storage_class();
|
||||
auto p = parser("not-a-storage-class");
|
||||
auto sc = p->storage_class();
|
||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsIdentifier());
|
||||
EXPECT_EQ(t.to_str(), "not");
|
||||
}
|
||||
|
|
|
@ -15,64 +15,60 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/type/i32_type.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, StructBodyDecl_Parses) {
|
||||
auto i32 =
|
||||
TypeManager::Instance()->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto i32 = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||
|
||||
ParserImpl p{"{a : i32;}"};
|
||||
auto m = p.struct_body_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("{a : i32;}");
|
||||
auto m = p->struct_body_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_EQ(m.size(), 1);
|
||||
|
||||
const auto& mem = m[0];
|
||||
EXPECT_EQ(mem->name(), "a");
|
||||
EXPECT_EQ(mem->type(), i32);
|
||||
EXPECT_EQ(mem->decorations().size(), 0);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructBodyDecl_ParsesEmpty) {
|
||||
ParserImpl p{"{}"};
|
||||
auto m = p.struct_body_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("{}");
|
||||
auto m = p->struct_body_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_EQ(m.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructBodyDecl_InvalidMember) {
|
||||
ParserImpl p{R"(
|
||||
auto p = parser(R"(
|
||||
{
|
||||
[[offset nan]] a : i32;
|
||||
})"};
|
||||
auto m = p.struct_body_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "3:12: invalid value for offset decoration");
|
||||
})");
|
||||
auto m = p->struct_body_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "3:12: invalid value for offset decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructBodyDecl_MissingClosingBracket) {
|
||||
ParserImpl p{"{a : i32;"};
|
||||
auto m = p.struct_body_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:10: missing } for struct declaration");
|
||||
auto p = parser("{a : i32;");
|
||||
auto m = p->struct_body_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:10: missing } for struct declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructBodyDecl_InvalidToken) {
|
||||
ParserImpl p{R"(
|
||||
auto p = parser(R"(
|
||||
{
|
||||
a : i32;
|
||||
1.23
|
||||
} )"};
|
||||
auto m = p.struct_body_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "4:3: invalid identifier declaration");
|
||||
} )");
|
||||
auto m = p->struct_body_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "4:3: invalid identifier declaration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,21 +15,20 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/type/struct_type.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, StructDecl_Parses) {
|
||||
ParserImpl p{R"(
|
||||
auto p = parser(R"(
|
||||
struct {
|
||||
a : i32;
|
||||
[[offset 4 ]] b : f32;
|
||||
})"};
|
||||
auto s = p.struct_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
})");
|
||||
auto s = p->struct_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(s, nullptr);
|
||||
ASSERT_EQ(s->impl()->members().size(), 2);
|
||||
EXPECT_EQ(s->impl()->members()[0]->name(), "a");
|
||||
|
@ -37,13 +36,13 @@ struct {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
|
||||
ParserImpl p{R"(
|
||||
auto p = parser(R"(
|
||||
[[block]] struct {
|
||||
a : f32;
|
||||
b : f32;
|
||||
})"};
|
||||
auto s = p.struct_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
})");
|
||||
auto s = p->struct_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(s, nullptr);
|
||||
ASSERT_EQ(s->impl()->members().size(), 2);
|
||||
EXPECT_EQ(s->impl()->members()[0]->name(), "a");
|
||||
|
@ -51,43 +50,43 @@ TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructDecl_EmptyMembers) {
|
||||
ParserImpl p{"struct {}"};
|
||||
auto s = p.struct_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("struct {}");
|
||||
auto s = p->struct_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(s, nullptr);
|
||||
ASSERT_EQ(s->impl()->members().size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructDecl_MissingBracketLeft) {
|
||||
ParserImpl p{"struct }"};
|
||||
auto s = p.struct_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("struct }");
|
||||
auto s = p->struct_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(s, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing { for struct declaration");
|
||||
EXPECT_EQ(p->error(), "1:8: missing { for struct declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructDecl_InvalidStructBody) {
|
||||
ParserImpl p{"struct { a : B; }"};
|
||||
auto s = p.struct_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("struct { a : B; }");
|
||||
auto s = p->struct_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(s, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: unknown type alias 'B'");
|
||||
EXPECT_EQ(p->error(), "1:14: unknown type alias 'B'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructDecl_InvalidStructDecorationDecl) {
|
||||
ParserImpl p{"[[block struct { a : i32; }"};
|
||||
auto s = p.struct_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("[[block struct { a : i32; }");
|
||||
auto s = p->struct_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(s, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: missing ]] for struct decoration");
|
||||
EXPECT_EQ(p->error(), "1:9: missing ]] for struct decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructDecl_MissingStruct) {
|
||||
ParserImpl p{"[[block]] {}"};
|
||||
auto s = p.struct_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("[[block]] {}");
|
||||
auto s = p->struct_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(s, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing struct declaration");
|
||||
EXPECT_EQ(p->error(), "1:11: missing struct declaration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -14,32 +14,31 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, StructDecorationDecl_Parses) {
|
||||
ParserImpl p{"[[block]]"};
|
||||
auto d = p.struct_decoration_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("[[block]]");
|
||||
auto d = p->struct_decoration_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(d, ast::StructDecoration::kBlock);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {
|
||||
ParserImpl p{"[[block"};
|
||||
p.struct_decoration_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:8: missing ]] for struct decoration");
|
||||
auto p = parser("[[block");
|
||||
p->struct_decoration_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:8: missing ]] for struct decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructDecorationDecl_InvalidDecoration) {
|
||||
ParserImpl p{"[[invalid]]"};
|
||||
p.struct_decoration_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:3: unknown struct decoration");
|
||||
auto p = parser("[[invalid]]");
|
||||
p->struct_decoration_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:3: unknown struct decoration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/struct_decoration.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
namespace {
|
||||
|
||||
struct StructDecorationData {
|
||||
const char* input;
|
||||
|
@ -30,16 +30,42 @@ inline std::ostream& operator<<(std::ostream& out, StructDecorationData data) {
|
|||
out << std::string(data.input);
|
||||
return out;
|
||||
}
|
||||
using StructDecorationTest = testing::TestWithParam<StructDecorationData>;
|
||||
|
||||
class StructDecorationTest
|
||||
: public testing::TestWithParam<StructDecorationData> {
|
||||
public:
|
||||
StructDecorationTest() = default;
|
||||
~StructDecorationTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_P(StructDecorationTest, Parses) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto p = parser(params.input);
|
||||
|
||||
auto deco = p.struct_decoration();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto deco = p->struct_decoration();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(deco, params.result);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsEof());
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||
|
@ -48,11 +74,11 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
"block", ast::StructDecoration::kBlock}));
|
||||
|
||||
TEST_F(ParserImplTest, StructDecoration_NoMatch) {
|
||||
ParserImpl p{"not-a-stage"};
|
||||
auto deco = p.struct_decoration();
|
||||
auto p = parser("not-a-stage");
|
||||
auto deco = p->struct_decoration();
|
||||
ASSERT_EQ(deco, ast::StructDecoration::kNone);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsIdentifier());
|
||||
EXPECT_EQ(t.to_str(), "not");
|
||||
}
|
||||
|
|
|
@ -15,54 +15,53 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/struct_member_offset_decoration.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_EmptyStr) {
|
||||
ParserImpl p{""};
|
||||
auto deco = p.struct_member_decoration_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("");
|
||||
auto deco = p->struct_member_decoration_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(deco.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_EmptyBlock) {
|
||||
ParserImpl p{"[[]]"};
|
||||
auto deco = p.struct_member_decoration_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:3: empty struct member decoration found");
|
||||
auto p = parser("[[]]");
|
||||
auto deco = p->struct_member_decoration_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:3: empty struct member decoration found");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_Single) {
|
||||
ParserImpl p{"[[offset 4]]"};
|
||||
auto deco = p.struct_member_decoration_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("[[offset 4]]");
|
||||
auto deco = p->struct_member_decoration_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_EQ(deco.size(), 1);
|
||||
EXPECT_TRUE(deco[0]->IsOffset());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_HandlesDuplicate) {
|
||||
ParserImpl p{"[[offset 2, offset 4]]"};
|
||||
auto deco = p.struct_member_decoration_decl();
|
||||
ASSERT_TRUE(p.has_error()) << p.error();
|
||||
EXPECT_EQ(p.error(), "1:21: duplicate offset decoration found");
|
||||
auto p = parser("[[offset 2, offset 4]]");
|
||||
auto deco = p->struct_member_decoration_decl();
|
||||
ASSERT_TRUE(p->has_error()) << p->error();
|
||||
EXPECT_EQ(p->error(), "1:21: duplicate offset decoration found");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_InvalidDecoration) {
|
||||
ParserImpl p{"[[offset nan]]"};
|
||||
auto deco = p.struct_member_decoration_decl();
|
||||
ASSERT_TRUE(p.has_error()) << p.error();
|
||||
EXPECT_EQ(p.error(), "1:10: invalid value for offset decoration");
|
||||
auto p = parser("[[offset nan]]");
|
||||
auto deco = p->struct_member_decoration_decl();
|
||||
ASSERT_TRUE(p->has_error()) << p->error();
|
||||
EXPECT_EQ(p->error(), "1:10: invalid value for offset decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMemberDecorationDecl_MissingClose) {
|
||||
ParserImpl p{"[[offset 4"};
|
||||
auto deco = p.struct_member_decoration_decl();
|
||||
ASSERT_TRUE(p.has_error()) << p.error();
|
||||
EXPECT_EQ(p.error(), "1:11: missing ]] for struct member decoration");
|
||||
auto p = parser("[[offset 4");
|
||||
auto deco = p->struct_member_decoration_decl();
|
||||
ASSERT_TRUE(p->has_error()) << p->error();
|
||||
EXPECT_EQ(p->error(), "1:11: missing ]] for struct member decoration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,18 +15,17 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/struct_member_offset_decoration.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, StructMemberDecoration_Offset) {
|
||||
ParserImpl p{"offset 4"};
|
||||
auto deco = p.struct_member_decoration();
|
||||
auto p = parser("offset 4");
|
||||
auto deco = p->struct_member_decoration();
|
||||
ASSERT_NE(deco, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_TRUE(deco->IsOffset());
|
||||
|
||||
auto o = deco->AsOffset();
|
||||
|
@ -34,19 +33,19 @@ TEST_F(ParserImplTest, StructMemberDecoration_Offset) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingValue) {
|
||||
ParserImpl p{"offset"};
|
||||
auto deco = p.struct_member_decoration();
|
||||
auto p = parser("offset");
|
||||
auto deco = p->struct_member_decoration();
|
||||
ASSERT_EQ(deco, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:7: invalid value for offset decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:7: invalid value for offset decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingInvalid) {
|
||||
ParserImpl p{"offset nan"};
|
||||
auto deco = p.struct_member_decoration();
|
||||
auto p = parser("offset nan");
|
||||
auto deco = p->struct_member_decoration();
|
||||
ASSERT_EQ(deco, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:8: invalid value for offset decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:8: invalid value for offset decoration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -16,37 +16,32 @@
|
|||
#include "src/ast/struct_member_offset_decoration.h"
|
||||
#include "src/ast/type/i32_type.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, StructMember_Parses) {
|
||||
auto i32 =
|
||||
TypeManager::Instance()->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto i32 = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||
|
||||
ParserImpl p{"a : i32;"};
|
||||
auto m = p.struct_member();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("a : i32;");
|
||||
auto m = p->struct_member();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(m, nullptr);
|
||||
|
||||
EXPECT_EQ(m->name(), "a");
|
||||
EXPECT_EQ(m->type(), i32);
|
||||
EXPECT_EQ(m->decorations().size(), 0);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
|
||||
auto i32 =
|
||||
TypeManager::Instance()->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto i32 = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||
|
||||
ParserImpl p{"[[offset 2]] a : i32;"};
|
||||
auto m = p.struct_member();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("[[offset 2]] a : i32;");
|
||||
auto m = p->struct_member();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(m, nullptr);
|
||||
|
||||
EXPECT_EQ(m->name(), "a");
|
||||
|
@ -54,32 +49,30 @@ TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
|
|||
EXPECT_EQ(m->decorations().size(), 1);
|
||||
EXPECT_TRUE(m->decorations()[0]->IsOffset());
|
||||
EXPECT_EQ(m->decorations()[0]->AsOffset()->offset(), 2);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMember_InvalidDecoration) {
|
||||
ParserImpl p{"[[offset nan]] a : i32;"};
|
||||
auto m = p.struct_member();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("[[offset nan]] a : i32;");
|
||||
auto m = p->struct_member();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(m, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: invalid value for offset decoration");
|
||||
EXPECT_EQ(p->error(), "1:10: invalid value for offset decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMember_InvalidVariable) {
|
||||
ParserImpl p{"[[offset 4]] a : B;"};
|
||||
auto m = p.struct_member();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("[[offset 4]] a : B;");
|
||||
auto m = p->struct_member();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(m, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:18: unknown type alias 'B'");
|
||||
EXPECT_EQ(p->error(), "1:18: unknown type alias 'B'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, StructMember_MissingSemicolon) {
|
||||
ParserImpl p{"a : i32"};
|
||||
auto m = p.struct_member();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("a : i32");
|
||||
auto m = p->struct_member();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(m, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing ; for struct member");
|
||||
EXPECT_EQ(p->error(), "1:8: missing ; for struct member");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,17 +15,16 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/case_statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case) {
|
||||
ParserImpl p{"case 1: { a = 4; }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("case 1: { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsCase());
|
||||
EXPECT_FALSE(e->IsDefault());
|
||||
|
@ -34,57 +33,57 @@ TEST_F(ParserImplTest, SwitchBody_Case) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
|
||||
ParserImpl p{"case a == 4: { a = 4; }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("case a == 4: { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: unable to parse case conditional");
|
||||
EXPECT_EQ(p->error(), "1:6: unable to parse case conditional");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_MissingConstLiteral) {
|
||||
ParserImpl p{"case: { a = 4; }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("case: { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: unable to parse case conditional");
|
||||
EXPECT_EQ(p->error(), "1:5: unable to parse case conditional");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_MissingColon) {
|
||||
ParserImpl p{"case 1 { a = 4; }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("case 1 { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing : for case statement");
|
||||
EXPECT_EQ(p->error(), "1:8: missing : for case statement");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketLeft) {
|
||||
ParserImpl p{"case 1: a = 4; }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("case 1: a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: missing { for case statement");
|
||||
EXPECT_EQ(p->error(), "1:9: missing { for case statement");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketRight) {
|
||||
ParserImpl p{"case 1: { a = 4; "};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("case 1: { a = 4; ");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:18: missing } for case statement");
|
||||
EXPECT_EQ(p->error(), "1:18: missing } for case statement");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_InvalidCaseBody) {
|
||||
ParserImpl p{"case 1: { fn main() -> void {} }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("case 1: { fn main() -> void {} }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing } for case statement");
|
||||
EXPECT_EQ(p->error(), "1:11: missing } for case statement");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Default) {
|
||||
ParserImpl p{"default: { a = 4; }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("default: { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsCase());
|
||||
EXPECT_TRUE(e->IsDefault());
|
||||
|
@ -93,35 +92,35 @@ TEST_F(ParserImplTest, SwitchBody_Default) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Default_MissingColon) {
|
||||
ParserImpl p{"default { a = 4; }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("default { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: missing : for case statement");
|
||||
EXPECT_EQ(p->error(), "1:9: missing : for case statement");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketLeft) {
|
||||
ParserImpl p{"default: a = 4; }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("default: a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: missing { for case statement");
|
||||
EXPECT_EQ(p->error(), "1:10: missing { for case statement");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketRight) {
|
||||
ParserImpl p{"default: { a = 4; "};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("default: { a = 4; ");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:19: missing } for case statement");
|
||||
EXPECT_EQ(p->error(), "1:19: missing } for case statement");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Default_InvalidCaseBody) {
|
||||
ParserImpl p{"default: { fn main() -> void {} }"};
|
||||
auto e = p.switch_body();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("default: { fn main() -> void {} }");
|
||||
auto e = p->switch_body();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: missing } for case statement");
|
||||
EXPECT_EQ(p->error(), "1:12: missing } for case statement");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -16,20 +16,19 @@
|
|||
#include "src/ast/case_statement.h"
|
||||
#include "src/ast/switch_statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, SwitchStmt_WithoutDefault) {
|
||||
ParserImpl p{R"(switch(a) {
|
||||
auto p = parser(R"(switch(a) {
|
||||
case 1: {}
|
||||
case 2: {}
|
||||
})"};
|
||||
auto e = p.switch_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
})");
|
||||
auto e = p->switch_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsSwitch());
|
||||
ASSERT_EQ(e->body().size(), 2);
|
||||
|
@ -38,22 +37,22 @@ TEST_F(ParserImplTest, SwitchStmt_WithoutDefault) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchStmt_Empty) {
|
||||
ParserImpl p{"switch(a) { }"};
|
||||
auto e = p.switch_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("switch(a) { }");
|
||||
auto e = p->switch_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsSwitch());
|
||||
ASSERT_EQ(e->body().size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchStmt_DefaultInMiddle) {
|
||||
ParserImpl p{R"(switch(a) {
|
||||
auto p = parser(R"(switch(a) {
|
||||
case 1: {}
|
||||
default: {}
|
||||
case 2: {}
|
||||
})"};
|
||||
auto e = p.switch_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
})");
|
||||
auto e = p->switch_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsSwitch());
|
||||
|
||||
|
@ -64,45 +63,45 @@ TEST_F(ParserImplTest, SwitchStmt_DefaultInMiddle) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchStmt_InvalidExpression) {
|
||||
ParserImpl p{"switch(a=b) {}"};
|
||||
auto e = p.switch_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("switch(a=b) {}");
|
||||
auto e = p->switch_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: expected )");
|
||||
EXPECT_EQ(p->error(), "1:9: expected )");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchStmt_MissingExpression) {
|
||||
ParserImpl p{"switch {}"};
|
||||
auto e = p.switch_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("switch {}");
|
||||
auto e = p->switch_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: expected (");
|
||||
EXPECT_EQ(p->error(), "1:8: expected (");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchStmt_MissingBracketLeft) {
|
||||
ParserImpl p{"switch(a) }"};
|
||||
auto e = p.switch_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("switch(a) }");
|
||||
auto e = p->switch_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing { for switch statement");
|
||||
EXPECT_EQ(p->error(), "1:11: missing { for switch statement");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchStmt_MissingBracketRight) {
|
||||
ParserImpl p{"switch(a) {"};
|
||||
auto e = p.switch_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("switch(a) {");
|
||||
auto e = p->switch_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: missing } for switch statement");
|
||||
EXPECT_EQ(p->error(), "1:12: missing } for switch statement");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchStmt_InvalidBody) {
|
||||
ParserImpl p{R"(switch(a) {
|
||||
auto p = parser(R"(switch(a) {
|
||||
case: {}
|
||||
})"};
|
||||
auto e = p.switch_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
})");
|
||||
auto e = p->switch_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "2:7: unable to parse case conditional");
|
||||
EXPECT_EQ(p->error(), "2:7: unable to parse case conditional");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -16,20 +16,19 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/ast/type/i32_type.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, Empty) {
|
||||
ParserImpl p{""};
|
||||
ASSERT_TRUE(p.Parse()) << p.error();
|
||||
auto p = parser("");
|
||||
ASSERT_TRUE(p->Parse()) << p->error();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, DISABLED_Parses) {
|
||||
ParserImpl p{R"(
|
||||
auto p = parser(R"(
|
||||
import "GLSL.std.430" as glsl;
|
||||
|
||||
[[location 0]] var<out> gl_FragColor : vec4<f32>;
|
||||
|
@ -37,41 +36,41 @@ import "GLSL.std.430" as glsl;
|
|||
fn main() -> void {
|
||||
gl_FragColor = vec4<f32>(.4, .2, .3, 1);
|
||||
}
|
||||
)"};
|
||||
ASSERT_TRUE(p.Parse()) << p.error();
|
||||
)");
|
||||
ASSERT_TRUE(p->Parse()) << p->error();
|
||||
|
||||
auto m = p.module();
|
||||
auto m = p->module();
|
||||
ASSERT_EQ(1, m.imports().size());
|
||||
|
||||
// TODO(dsinclair) check rest of AST ...
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, DISABLED_HandlesError) {
|
||||
ParserImpl p{R"(
|
||||
auto p = parser(R"(
|
||||
import "GLSL.std.430" as glsl;
|
||||
|
||||
fn main() -> { # missing return type
|
||||
return;
|
||||
})"};
|
||||
})");
|
||||
|
||||
ASSERT_FALSE(p.Parse());
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "4:15: missing return type for function");
|
||||
ASSERT_FALSE(p->Parse());
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "4:15: missing return type for function");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GetRegisteredType) {
|
||||
ParserImpl p{""};
|
||||
auto p = parser("");
|
||||
ast::type::I32Type i32;
|
||||
p.register_alias("my_alias", &i32);
|
||||
p->register_alias("my_alias", &i32);
|
||||
|
||||
auto alias = p.get_alias("my_alias");
|
||||
auto alias = p->get_alias("my_alias");
|
||||
ASSERT_NE(alias, nullptr);
|
||||
ASSERT_EQ(alias, &i32);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GetUnregisteredType) {
|
||||
ParserImpl p{""};
|
||||
auto alias = p.get_alias("my_alias");
|
||||
auto p = parser("");
|
||||
auto alias = p->get_alias("my_alias");
|
||||
ASSERT_EQ(alias, nullptr);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
// 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.
|
||||
|
||||
#ifndef SRC_READER_WGSL_PARSER_IMPL_TEST_HELPER_H_
|
||||
#define SRC_READER_WGSL_PARSER_IMPL_TEST_HELPER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/context.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
class ParserImplTest : public testing::Test {
|
||||
public:
|
||||
ParserImplTest() = default;
|
||||
~ParserImplTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = nullptr;
|
||||
}
|
||||
|
||||
ParserImpl* parser(const std::string& str) {
|
||||
impl_ = std::make_unique<ParserImpl>(ctx_, str);
|
||||
return impl_.get();
|
||||
}
|
||||
|
||||
TypeManager* tm() { return &tm_; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<ParserImpl> impl_;
|
||||
Context ctx_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
} // namespace wgsl
|
||||
} // namespace reader
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_READER_WGSL_PARSER_IMPL_TEST_HELPER_H_
|
|
@ -17,32 +17,28 @@
|
|||
#include "src/ast/type/i32_type.h"
|
||||
#include "src/ast/type/struct_type.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_ParsesType) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto i32 = tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto i32 = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||
|
||||
ParserImpl p{"type a = i32"};
|
||||
auto t = p.type_alias();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("type a = i32");
|
||||
auto t = p->type_alias();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(t, nullptr);
|
||||
ASSERT_TRUE(t->type()->IsI32());
|
||||
ASSERT_EQ(t->type(), i32);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_ParsesStruct) {
|
||||
ParserImpl p{"type a = struct { b: i32; c: f32;}"};
|
||||
auto t = p.type_alias();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("type a = struct { b: i32; c: f32;}");
|
||||
auto t = p->type_alias();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(t, nullptr);
|
||||
EXPECT_EQ(t->name(), "a");
|
||||
ASSERT_TRUE(t->type()->IsStruct());
|
||||
|
@ -52,43 +48,43 @@ TEST_F(ParserImplTest, TypeDecl_ParsesStruct) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_MissingIdent) {
|
||||
ParserImpl p{"type = i32"};
|
||||
auto t = p.type_alias();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("type = i32");
|
||||
auto t = p->type_alias();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(t, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing identifier for type alias");
|
||||
EXPECT_EQ(p->error(), "1:6: missing identifier for type alias");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_InvalidIdent) {
|
||||
ParserImpl p{"type 123 = i32"};
|
||||
auto t = p.type_alias();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("type 123 = i32");
|
||||
auto t = p->type_alias();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(t, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing identifier for type alias");
|
||||
EXPECT_EQ(p->error(), "1:6: missing identifier for type alias");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_MissingEqual) {
|
||||
ParserImpl p{"type a i32"};
|
||||
auto t = p.type_alias();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("type a i32");
|
||||
auto t = p->type_alias();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(t, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing = for type alias");
|
||||
EXPECT_EQ(p->error(), "1:8: missing = for type alias");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_InvalidType) {
|
||||
ParserImpl p{"type a = B"};
|
||||
auto t = p.type_alias();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("type a = B");
|
||||
auto t = p->type_alias();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(t, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:10: unknown type alias 'B'");
|
||||
EXPECT_EQ(p->error(), "1:10: unknown type alias 'B'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_InvalidStruct) {
|
||||
ParserImpl p{"type a = [[block]] {}"};
|
||||
auto t = p.type_alias();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("type a = [[block]] {}");
|
||||
auto t = p->type_alias();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(t, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:20: missing struct declaration");
|
||||
EXPECT_EQ(p->error(), "1:20: missing struct declaration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -24,33 +24,31 @@
|
|||
#include "src/ast/type/u32_type.h"
|
||||
#include "src/ast/type/vector_type.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Invalid) {
|
||||
ParserImpl p{"1234"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("1234");
|
||||
auto t = p->type_decl();
|
||||
EXPECT_EQ(t, nullptr);
|
||||
EXPECT_FALSE(p.has_error());
|
||||
EXPECT_FALSE(p->has_error());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Identifier) {
|
||||
ParserImpl p{"A"};
|
||||
auto p = parser("A");
|
||||
|
||||
auto tm = TypeManager::Instance();
|
||||
auto int_type = tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto int_type = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||
// Pre-register to make sure that it's the same type.
|
||||
auto alias_type =
|
||||
tm->Get(std::make_unique<ast::type::AliasType>("A", int_type));
|
||||
tm()->Get(std::make_unique<ast::type::AliasType>("A", int_type));
|
||||
|
||||
p.register_alias("A", alias_type);
|
||||
p->register_alias("A", alias_type);
|
||||
|
||||
auto t = p.type_decl();
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr);
|
||||
EXPECT_EQ(t, alias_type);
|
||||
ASSERT_TRUE(t->IsAlias());
|
||||
|
@ -58,73 +56,59 @@ TEST_F(ParserImplTest, TypeDecl_Identifier) {
|
|||
auto alias = t->AsAlias();
|
||||
EXPECT_EQ(alias->name(), "A");
|
||||
EXPECT_EQ(alias->type(), int_type);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Identifier_NotFound) {
|
||||
ParserImpl p{"B"};
|
||||
auto p = parser("B");
|
||||
|
||||
auto t = p.type_decl();
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
EXPECT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:1: unknown type alias 'B'");
|
||||
EXPECT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:1: unknown type alias 'B'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Bool) {
|
||||
ParserImpl p{"bool"};
|
||||
auto p = parser("bool");
|
||||
|
||||
auto tm = TypeManager::Instance();
|
||||
auto bool_type = tm->Get(std::make_unique<ast::type::BoolType>());
|
||||
auto bool_type = tm()->Get(std::make_unique<ast::type::BoolType>());
|
||||
|
||||
auto t = p.type_decl();
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr);
|
||||
EXPECT_EQ(t, bool_type);
|
||||
ASSERT_TRUE(t->IsBool());
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_F32) {
|
||||
ParserImpl p{"f32"};
|
||||
auto p = parser("f32");
|
||||
|
||||
auto tm = TypeManager::Instance();
|
||||
auto float_type = tm->Get(std::make_unique<ast::type::F32Type>());
|
||||
auto float_type = tm()->Get(std::make_unique<ast::type::F32Type>());
|
||||
|
||||
auto t = p.type_decl();
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr);
|
||||
EXPECT_EQ(t, float_type);
|
||||
ASSERT_TRUE(t->IsF32());
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_I32) {
|
||||
ParserImpl p{"i32"};
|
||||
auto p = parser("i32");
|
||||
|
||||
auto tm = TypeManager::Instance();
|
||||
auto int_type = tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto int_type = tm()->Get(std::make_unique<ast::type::I32Type>());
|
||||
|
||||
auto t = p.type_decl();
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr);
|
||||
EXPECT_EQ(t, int_type);
|
||||
ASSERT_TRUE(t->IsI32());
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_U32) {
|
||||
ParserImpl p{"u32"};
|
||||
auto p = parser("u32");
|
||||
|
||||
auto tm = TypeManager::Instance();
|
||||
auto uint_type = tm->Get(std::make_unique<ast::type::U32Type>());
|
||||
auto uint_type = tm()->Get(std::make_unique<ast::type::U32Type>());
|
||||
|
||||
auto t = p.type_decl();
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr);
|
||||
EXPECT_EQ(t, uint_type);
|
||||
ASSERT_TRUE(t->IsU32());
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
struct VecData {
|
||||
|
@ -135,13 +119,35 @@ inline std::ostream& operator<<(std::ostream& out, VecData data) {
|
|||
out << std::string(data.input);
|
||||
return out;
|
||||
}
|
||||
using VecTest = testing::TestWithParam<VecData>;
|
||||
class VecTest : public testing::TestWithParam<VecData> {
|
||||
public:
|
||||
VecTest() = default;
|
||||
~VecTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
TEST_P(VecTest, Parse) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_TRUE(t->IsVector());
|
||||
EXPECT_EQ(t->AsVector()->size(), params.count);
|
||||
}
|
||||
|
@ -151,14 +157,36 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
VecData{"vec3<f32>", 3},
|
||||
VecData{"vec4<f32>", 4}));
|
||||
|
||||
using VecMissingGreaterThanTest = testing::TestWithParam<VecData>;
|
||||
class VecMissingGreaterThanTest : public testing::TestWithParam<VecData> {
|
||||
public:
|
||||
VecMissingGreaterThanTest() = default;
|
||||
~VecMissingGreaterThanTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
TEST_P(VecMissingGreaterThanTest, Handles_Missing_GreaterThan) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:9: missing > for vector");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:9: missing > for vector");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||
VecMissingGreaterThanTest,
|
||||
|
@ -166,14 +194,36 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
VecData{"vec3<f32", 3},
|
||||
VecData{"vec4<f32", 4}));
|
||||
|
||||
using VecMissingLessThanTest = testing::TestWithParam<VecData>;
|
||||
class VecMissingLessThanTest : public testing::TestWithParam<VecData> {
|
||||
public:
|
||||
VecMissingLessThanTest() = default;
|
||||
~VecMissingLessThanTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
TEST_P(VecMissingLessThanTest, Handles_Missing_GreaterThan) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:5: missing < for vector");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:5: missing < for vector");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||
VecMissingLessThanTest,
|
||||
|
@ -181,14 +231,36 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
VecData{"vec3", 3},
|
||||
VecData{"vec4", 4}));
|
||||
|
||||
using VecBadType = testing::TestWithParam<VecData>;
|
||||
class VecBadType : public testing::TestWithParam<VecData> {
|
||||
public:
|
||||
VecBadType() = default;
|
||||
~VecBadType() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
TEST_P(VecBadType, Handles_Unknown_Type) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:6: unknown type alias 'unknown'");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:6: unknown type alias 'unknown'");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||
VecBadType,
|
||||
|
@ -196,14 +268,36 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
VecData{"vec3<unknown", 3},
|
||||
VecData{"vec4<unknown", 4}));
|
||||
|
||||
using VecMissingType = testing::TestWithParam<VecData>;
|
||||
class VecMissingType : public testing::TestWithParam<VecData> {
|
||||
public:
|
||||
VecMissingType() = default;
|
||||
~VecMissingType() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
TEST_P(VecMissingType, Handles_Missing_Type) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:6: unable to determine subtype for vector");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:6: unable to determine subtype for vector");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||
VecMissingType,
|
||||
|
@ -212,10 +306,10 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
VecData{"vec4<>", 4}));
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr) {
|
||||
ParserImpl p{"ptr<function, f32>"};
|
||||
auto t = p.type_decl();
|
||||
ASSERT_NE(t, nullptr) << p.error();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("ptr<function, f32>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr) << p->error();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_TRUE(t->IsPointer());
|
||||
|
||||
auto ptr = t->AsPointer();
|
||||
|
@ -224,10 +318,10 @@ TEST_F(ParserImplTest, TypeDecl_Ptr) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) {
|
||||
ParserImpl p{"ptr<function, vec2<f32>>"};
|
||||
auto t = p.type_decl();
|
||||
ASSERT_NE(t, nullptr) << p.error();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("ptr<function, vec2<f32>>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr) << p->error();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_TRUE(t->IsPointer());
|
||||
|
||||
auto ptr = t->AsPointer();
|
||||
|
@ -240,74 +334,74 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingLessThan) {
|
||||
ParserImpl p{"ptr private, f32>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("ptr private, f32>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:5: missing < for ptr declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:5: missing < for ptr declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThan) {
|
||||
ParserImpl p{"ptr<function, f32"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("ptr<function, f32");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:18: missing > for ptr declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:18: missing > for ptr declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingComma) {
|
||||
ParserImpl p{"ptr<function f32>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("ptr<function f32>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:14: missing , for ptr declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:14: missing , for ptr declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingStorageClass) {
|
||||
ParserImpl p{"ptr<, f32>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("ptr<, f32>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:5: missing storage class for ptr declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:5: missing storage class for ptr declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingParams) {
|
||||
ParserImpl p{"ptr<>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("ptr<>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:5: missing storage class for ptr declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:5: missing storage class for ptr declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingType) {
|
||||
ParserImpl p{"ptr<function,>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("ptr<function,>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:14: missing type for ptr declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:14: missing type for ptr declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr_BadStorageClass) {
|
||||
ParserImpl p{"ptr<unknown, f32>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("ptr<unknown, f32>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:5: missing storage class for ptr declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:5: missing storage class for ptr declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Ptr_BadType) {
|
||||
ParserImpl p{"ptr<function, unknown>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("ptr<function, unknown>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:15: unknown type alias 'unknown'");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:15: unknown type alias 'unknown'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array) {
|
||||
ParserImpl p{"array<f32, 5>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("array<f32, 5>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_TRUE(t->IsArray());
|
||||
|
||||
auto a = t->AsArray();
|
||||
|
@ -317,10 +411,10 @@ TEST_F(ParserImplTest, TypeDecl_Array) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_Runtime) {
|
||||
ParserImpl p{"array<u32>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("array<u32>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_TRUE(t->IsArray());
|
||||
|
||||
auto a = t->AsArray();
|
||||
|
@ -329,59 +423,59 @@ TEST_F(ParserImplTest, TypeDecl_Array_Runtime) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_BadType) {
|
||||
ParserImpl p{"array<unknown, 3>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("array<unknown, 3>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:7: unknown type alias 'unknown'");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:7: unknown type alias 'unknown'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_ZeroSize) {
|
||||
ParserImpl p{"array<f32, 0>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("array<f32, 0>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:12: invalid size for array declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:12: invalid size for array declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_NegativeSize) {
|
||||
ParserImpl p{"array<f32, -1>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("array<f32, -1>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:12: invalid size for array declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:12: invalid size for array declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_BadSize) {
|
||||
ParserImpl p{"array<f32, invalid>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("array<f32, invalid>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:12: missing size of array declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:12: missing size of array declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_MissingLessThan) {
|
||||
ParserImpl p{"array f32>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("array f32>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:7: missing < for array declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:7: missing < for array declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_MissingGreaterThan) {
|
||||
ParserImpl p{"array<f32"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("array<f32");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:10: missing > for array declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:10: missing > for array declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, TypeDecl_Array_MissingComma) {
|
||||
ParserImpl p{"array<f32 3>"};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser("array<f32 3>");
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:11: missing > for array declaration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:11: missing > for array declaration");
|
||||
}
|
||||
|
||||
struct MatrixData {
|
||||
|
@ -393,13 +487,35 @@ inline std::ostream& operator<<(std::ostream& out, MatrixData data) {
|
|||
out << std::string(data.input);
|
||||
return out;
|
||||
}
|
||||
using MatrixTest = testing::TestWithParam<MatrixData>;
|
||||
class MatrixTest : public testing::TestWithParam<MatrixData> {
|
||||
public:
|
||||
MatrixTest() = default;
|
||||
~MatrixTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
TEST_P(MatrixTest, Parse) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_NE(t, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_TRUE(t->IsMatrix());
|
||||
auto mat = t->AsMatrix();
|
||||
EXPECT_EQ(mat->rows(), params.rows);
|
||||
|
@ -417,14 +533,35 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
MatrixData{"mat4x3<f32>", 4, 3},
|
||||
MatrixData{"mat4x4<f32>", 4, 4}));
|
||||
|
||||
using MatrixMissingGreaterThanTest = testing::TestWithParam<MatrixData>;
|
||||
class MatrixMissingGreaterThanTest : public testing::TestWithParam<MatrixData> {
|
||||
public:
|
||||
MatrixMissingGreaterThanTest() = default;
|
||||
~MatrixMissingGreaterThanTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
TEST_P(MatrixMissingGreaterThanTest, Handles_Missing_GreaterThan) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:11: missing > for matrix");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:11: missing > for matrix");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||
MatrixMissingGreaterThanTest,
|
||||
|
@ -438,14 +575,35 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
MatrixData{"mat4x3<f32", 4, 3},
|
||||
MatrixData{"mat4x4<f32", 4, 4}));
|
||||
|
||||
using MatrixMissingLessThanTest = testing::TestWithParam<MatrixData>;
|
||||
class MatrixMissingLessThanTest : public testing::TestWithParam<MatrixData> {
|
||||
public:
|
||||
MatrixMissingLessThanTest() = default;
|
||||
~MatrixMissingLessThanTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
TEST_P(MatrixMissingLessThanTest, Handles_Missing_GreaterThan) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:8: missing < for matrix");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:8: missing < for matrix");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||
MatrixMissingLessThanTest,
|
||||
|
@ -459,14 +617,35 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
MatrixData{"mat4x3 f32>", 4, 3},
|
||||
MatrixData{"mat4x4 f32>", 4, 4}));
|
||||
|
||||
using MatrixBadType = testing::TestWithParam<MatrixData>;
|
||||
class MatrixBadType : public testing::TestWithParam<MatrixData> {
|
||||
public:
|
||||
MatrixBadType() = default;
|
||||
~MatrixBadType() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
TEST_P(MatrixBadType, Handles_Unknown_Type) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:8: unknown type alias 'unknown'");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:8: unknown type alias 'unknown'");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||
MatrixBadType,
|
||||
|
@ -480,14 +659,35 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
|||
MatrixData{"mat4x3<unknown>", 4, 3},
|
||||
MatrixData{"mat4x4<unknown>", 4, 4}));
|
||||
|
||||
using MatrixMissingType = testing::TestWithParam<MatrixData>;
|
||||
class MatrixMissingType : public testing::TestWithParam<MatrixData> {
|
||||
public:
|
||||
MatrixMissingType() = default;
|
||||
~MatrixMissingType() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
TEST_P(MatrixMissingType, Handles_Missing_Type) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{params.input};
|
||||
auto t = p.type_decl();
|
||||
auto p = parser(params.input);
|
||||
auto t = p->type_decl();
|
||||
ASSERT_EQ(t, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:8: unable to determine subtype for matrix");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:8: unable to determine subtype for matrix");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
|
||||
MatrixMissingType,
|
||||
|
|
|
@ -21,17 +21,16 @@
|
|||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Postix) {
|
||||
ParserImpl p{"a[2]"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("a[2]");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
|
||||
ASSERT_TRUE(e->IsArrayAccessor());
|
||||
|
@ -49,9 +48,9 @@ TEST_F(ParserImplTest, UnaryExpression_Postix) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Minus) {
|
||||
ParserImpl p{"- 1"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("- 1");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryOp());
|
||||
|
||||
|
@ -67,17 +66,17 @@ TEST_F(ParserImplTest, UnaryExpression_Minus) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Minus_InvalidRHS) {
|
||||
ParserImpl p{"-if(a) {}"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("-if(a) {}");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:2: unable to parse right side of - expression");
|
||||
EXPECT_EQ(p->error(), "1:2: unable to parse right side of - expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Bang) {
|
||||
ParserImpl p{"!1"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("!1");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryOp());
|
||||
|
||||
|
@ -93,17 +92,17 @@ TEST_F(ParserImplTest, UnaryExpression_Bang) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) {
|
||||
ParserImpl p{"!if (a) {}"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("!if (a) {}");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:2: unable to parse right side of ! expression");
|
||||
EXPECT_EQ(p->error(), "1:2: unable to parse right side of ! expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any) {
|
||||
ParserImpl p{"any(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("any(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
|
@ -117,41 +116,41 @@ TEST_F(ParserImplTest, UnaryExpression_Any) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any_MissingParenLeft) {
|
||||
ParserImpl p{"any a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("any a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing ( for method call");
|
||||
EXPECT_EQ(p->error(), "1:5: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any_MissingParenRight) {
|
||||
ParserImpl p{"any(a"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("any(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing ) for method call");
|
||||
EXPECT_EQ(p->error(), "1:6: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any_MissingIdentifier) {
|
||||
ParserImpl p{"any()"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("any()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any_InvalidIdentifier) {
|
||||
ParserImpl p{"any(123)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("any(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All) {
|
||||
ParserImpl p{"all(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("all(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
|
@ -165,41 +164,41 @@ TEST_F(ParserImplTest, UnaryExpression_All) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All_MissingParenLeft) {
|
||||
ParserImpl p{"all a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("all a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing ( for method call");
|
||||
EXPECT_EQ(p->error(), "1:5: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All_MissingParenRight) {
|
||||
ParserImpl p{"all(a"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("all(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing ) for method call");
|
||||
EXPECT_EQ(p->error(), "1:6: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All_MissingIdentifier) {
|
||||
ParserImpl p{"all()"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("all()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All_InvalidIdentifier) {
|
||||
ParserImpl p{"all(123)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("all(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan) {
|
||||
ParserImpl p{"is_nan(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("is_nan(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
|
@ -213,41 +212,41 @@ TEST_F(ParserImplTest, UnaryExpression_IsNan) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan_MissingParenLeft) {
|
||||
ParserImpl p{"is_nan a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_nan a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing ( for method call");
|
||||
EXPECT_EQ(p->error(), "1:8: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan_MissingParenRight) {
|
||||
ParserImpl p{"is_nan(a"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_nan(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: missing ) for method call");
|
||||
EXPECT_EQ(p->error(), "1:9: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan_MissingIdentifier) {
|
||||
ParserImpl p{"is_nan()"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_nan()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan_InvalidIdentifier) {
|
||||
ParserImpl p{"is_nan(123)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_nan(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf) {
|
||||
ParserImpl p{"is_inf(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("is_inf(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
|
@ -261,41 +260,41 @@ TEST_F(ParserImplTest, UnaryExpression_IsInf) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf_MissingParenLeft) {
|
||||
ParserImpl p{"is_inf a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_inf a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing ( for method call");
|
||||
EXPECT_EQ(p->error(), "1:8: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf_MissingParenRight) {
|
||||
ParserImpl p{"is_inf(a"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_inf(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: missing ) for method call");
|
||||
EXPECT_EQ(p->error(), "1:9: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf_MissingIdentifier) {
|
||||
ParserImpl p{"is_inf()"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_inf()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf_InvalidIdentifier) {
|
||||
ParserImpl p{"is_inf(123)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_inf(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite) {
|
||||
ParserImpl p{"is_finite(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("is_finite(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
|
@ -309,41 +308,41 @@ TEST_F(ParserImplTest, UnaryExpression_IsFinite) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite_MissingParenLeft) {
|
||||
ParserImpl p{"is_finite a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_finite a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing ( for method call");
|
||||
EXPECT_EQ(p->error(), "1:11: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite_MissingParenRight) {
|
||||
ParserImpl p{"is_finite(a"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_finite(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: missing ) for method call");
|
||||
EXPECT_EQ(p->error(), "1:12: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite_MissingIdentifier) {
|
||||
ParserImpl p{"is_finite()"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_finite()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:11: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite_InvalidIdentifier) {
|
||||
ParserImpl p{"is_finite(123)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_finite(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:11: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal) {
|
||||
ParserImpl p{"is_normal(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("is_normal(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
|
@ -357,41 +356,41 @@ TEST_F(ParserImplTest, UnaryExpression_IsNormal) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal_MissingParenLeft) {
|
||||
ParserImpl p{"is_normal a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_normal a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing ( for method call");
|
||||
EXPECT_EQ(p->error(), "1:11: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal_MissingParenRight) {
|
||||
ParserImpl p{"is_normal(a"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_normal(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:12: missing ) for method call");
|
||||
EXPECT_EQ(p->error(), "1:12: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal_MissingIdentifier) {
|
||||
ParserImpl p{"is_normal()"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_normal()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:11: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal_InvalidIdentifier) {
|
||||
ParserImpl p{"is_normal(123)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("is_normal(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:11: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot) {
|
||||
ParserImpl p{"dot(a, b)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("dot(a, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
|
@ -410,65 +409,65 @@ TEST_F(ParserImplTest, UnaryExpression_Dot) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingParenLeft) {
|
||||
ParserImpl p{"dot a, b)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dot a, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing ( for method call");
|
||||
EXPECT_EQ(p->error(), "1:5: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingParenRight) {
|
||||
ParserImpl p{"dot(a, b"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dot(a, b");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: missing ) for method call");
|
||||
EXPECT_EQ(p->error(), "1:9: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingFirstIdentifier) {
|
||||
ParserImpl p{"dot(, a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dot(, a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingSecondIdentifier) {
|
||||
ParserImpl p{"dot(a, )"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dot(a, )");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingComma) {
|
||||
ParserImpl p{"dot(a b)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dot(a b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:7: missing , for method call");
|
||||
EXPECT_EQ(p->error(), "1:7: missing , for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_InvalidFirstIdentifier) {
|
||||
ParserImpl p{"dot(123, b)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dot(123, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_InvalidSecondIdentifier) {
|
||||
ParserImpl p{"dot(a, 123)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dot(a, 123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct) {
|
||||
ParserImpl p{"outer_product(a, b)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("outer_product(a, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
|
@ -487,65 +486,65 @@ TEST_F(ParserImplTest, UnaryExpression_OuterProduct) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingParenLeft) {
|
||||
ParserImpl p{"outer_product a, b)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("outer_product a, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: missing ( for method call");
|
||||
EXPECT_EQ(p->error(), "1:15: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingParenRight) {
|
||||
ParserImpl p{"outer_product(a, b"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("outer_product(a, b");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:19: missing ) for method call");
|
||||
EXPECT_EQ(p->error(), "1:19: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingFirstIdentifier) {
|
||||
ParserImpl p{"outer_product(, b)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("outer_product(, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:15: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingSecondIdentifier) {
|
||||
ParserImpl p{"outer_product(a, )"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("outer_product(a, )");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:18: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:18: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingComma) {
|
||||
ParserImpl p{"outer_product(a b)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("outer_product(a b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:17: missing , for method call");
|
||||
EXPECT_EQ(p->error(), "1:17: missing , for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_InvalidFirstIdentifier) {
|
||||
ParserImpl p{"outer_product(123, b)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("outer_product(123, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:15: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_InvalidSecondIdentifier) {
|
||||
ParserImpl p{"outer_product(a, 123)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("outer_product(a, 123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:18: missing identifier for method call");
|
||||
EXPECT_EQ(p->error(), "1:18: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_NoModifier) {
|
||||
ParserImpl p{"dpdx(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("dpdx(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
|
@ -561,9 +560,9 @@ TEST_F(ParserImplTest, UnaryExpression_Dpdx_NoModifier) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_WithModifier) {
|
||||
ParserImpl p{"dpdx<coarse>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("dpdx<coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
|
@ -579,73 +578,73 @@ TEST_F(ParserImplTest, UnaryExpression_Dpdx_WithModifier) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MissingLessThan) {
|
||||
ParserImpl p{"dpdx coarse>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdx coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing ( for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:6: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_InvalidModifier) {
|
||||
ParserImpl p{"dpdx<invalid>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdx<invalid>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: unable to parse derivative modifier");
|
||||
EXPECT_EQ(p->error(), "1:6: unable to parse derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_EmptyModifer) {
|
||||
ParserImpl p{"dpdx coarse>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdx coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing ( for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:6: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MissingGreaterThan) {
|
||||
ParserImpl p{"dpdx<coarse (a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdx<coarse (a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: missing > for derivative modifier");
|
||||
EXPECT_EQ(p->error(), "1:13: missing > for derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MisisngLeftParen) {
|
||||
ParserImpl p{"dpdx<coarse>a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdx<coarse>a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: missing ( for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:13: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MissingRightParen) {
|
||||
ParserImpl p{"dpdx<coarse>(a"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdx<coarse>(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: missing ) for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:15: missing ) for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MissingIdentifier) {
|
||||
ParserImpl p{"dpdx<coarse>()"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdx<coarse>()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: missing identifier for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:14: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_InvalidIdentifeir) {
|
||||
ParserImpl p{"dpdx<coarse>(12345)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdx<coarse>(12345)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: missing identifier for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:14: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_NoModifier) {
|
||||
ParserImpl p{"dpdy(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("dpdy(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
|
@ -661,9 +660,9 @@ TEST_F(ParserImplTest, UnaryExpression_Dpdy_NoModifier) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_WithModifier) {
|
||||
ParserImpl p{"dpdy<fine>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("dpdy<fine>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
|
@ -679,73 +678,73 @@ TEST_F(ParserImplTest, UnaryExpression_Dpdy_WithModifier) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MissingLessThan) {
|
||||
ParserImpl p{"dpdy coarse>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdy coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing ( for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:6: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_InvalidModifier) {
|
||||
ParserImpl p{"dpdy<invalid>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdy<invalid>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: unable to parse derivative modifier");
|
||||
EXPECT_EQ(p->error(), "1:6: unable to parse derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_EmptyModifer) {
|
||||
ParserImpl p{"dpdy coarse>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdy coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:6: missing ( for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:6: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MissingGreaterThan) {
|
||||
ParserImpl p{"dpdy<coarse (a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdy<coarse (a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: missing > for derivative modifier");
|
||||
EXPECT_EQ(p->error(), "1:13: missing > for derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MisisngLeftParen) {
|
||||
ParserImpl p{"dpdy<coarse>a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdy<coarse>a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:13: missing ( for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:13: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MissingRightParen) {
|
||||
ParserImpl p{"dpdy<coarse>(a"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdy<coarse>(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: missing ) for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:15: missing ) for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MissingIdentifier) {
|
||||
ParserImpl p{"dpdy<coarse>()"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdy<coarse>()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: missing identifier for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:14: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_InvalidIdentifeir) {
|
||||
ParserImpl p{"dpdy<coarse>(12345)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("dpdy<coarse>(12345)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:14: missing identifier for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:14: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_NoModifier) {
|
||||
ParserImpl p{"fwidth(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("fwidth(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
|
@ -761,9 +760,9 @@ TEST_F(ParserImplTest, UnaryExpression_Fwidth_NoModifier) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_WithModifier) {
|
||||
ParserImpl p{"fwidth<coarse>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("fwidth<coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
|
@ -779,67 +778,67 @@ TEST_F(ParserImplTest, UnaryExpression_Fwidth_WithModifier) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MissingLessThan) {
|
||||
ParserImpl p{"fwidth coarse>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fwidth coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing ( for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:8: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_InvalidModifier) {
|
||||
ParserImpl p{"fwidth<invalid>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fwidth<invalid>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: unable to parse derivative modifier");
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_EmptyModifer) {
|
||||
ParserImpl p{"fwidth coarse>(a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fwidth coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: missing ( for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:8: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MissingGreaterThan) {
|
||||
ParserImpl p{"fwidth<coarse (a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fwidth<coarse (a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: missing > for derivative modifier");
|
||||
EXPECT_EQ(p->error(), "1:15: missing > for derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MisisngLeftParen) {
|
||||
ParserImpl p{"fwidth<coarse>a)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fwidth<coarse>a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: missing ( for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:15: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MissingRightParen) {
|
||||
ParserImpl p{"fwidth<coarse>(a"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fwidth<coarse>(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:17: missing ) for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:17: missing ) for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MissingIdentifier) {
|
||||
ParserImpl p{"fwidth<coarse>()"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fwidth<coarse>()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:16: missing identifier for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:16: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidht_InvalidIdentifeir) {
|
||||
ParserImpl p{"fwidth<coarse>(12345)"};
|
||||
auto e = p.unary_expression();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("fwidth<coarse>(12345)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:16: missing identifier for derivative method");
|
||||
EXPECT_EQ(p->error(), "1:16: missing identifier for derivative method");
|
||||
}
|
||||
} // namespace wgsl
|
||||
} // namespace reader
|
||||
|
|
|
@ -14,17 +14,16 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, UnlessStmt) {
|
||||
ParserImpl p{"unless (a) { kill; }"};
|
||||
auto e = p.unless_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("unless (a) { kill; }");
|
||||
auto e = p->unless_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnless());
|
||||
ASSERT_NE(e->condition(), nullptr);
|
||||
|
@ -34,27 +33,27 @@ TEST_F(ParserImplTest, UnlessStmt) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnlessStmt_InvalidCondition) {
|
||||
ParserImpl p{"unless(if(a){}) {}"};
|
||||
auto e = p.unless_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("unless(if(a){}) {}");
|
||||
auto e = p->unless_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnlessStmt_EmptyCondition) {
|
||||
ParserImpl p{"unless() {}"};
|
||||
auto e = p.unless_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("unless() {}");
|
||||
auto e = p->unless_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:8: unable to parse expression");
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnlessStmt_InvalidBody) {
|
||||
ParserImpl p{"unless(a + 2 - 5 == true) { kill }"};
|
||||
auto e = p.unless_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("unless(a + 2 - 5 == true) { kill }");
|
||||
auto e = p->unless_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:34: missing ;");
|
||||
EXPECT_EQ(p->error(), "1:34: missing ;");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,17 +15,16 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecl_Parses) {
|
||||
ParserImpl p{"var my_var : f32"};
|
||||
auto var = p.variable_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("var my_var : f32");
|
||||
auto var = p->variable_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(var, nullptr);
|
||||
ASSERT_EQ(var->name(), "my_var");
|
||||
ASSERT_NE(var->type(), nullptr);
|
||||
|
@ -35,27 +34,27 @@ TEST_F(ParserImplTest, VariableDecl_Parses) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecl_MissingVar) {
|
||||
ParserImpl p{"my_var : f32"};
|
||||
auto v = p.variable_decl();
|
||||
auto p = parser("my_var : f32");
|
||||
auto v = p->variable_decl();
|
||||
ASSERT_EQ(v, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
ASSERT_TRUE(t.IsIdentifier());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecl_InvalidIdentDecl) {
|
||||
ParserImpl p{"var my_var f32"};
|
||||
auto v = p.variable_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("var my_var f32");
|
||||
auto v = p->variable_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(v, nullptr);
|
||||
ASSERT_EQ(p.error(), "1:12: missing : for identifier declaration");
|
||||
ASSERT_EQ(p->error(), "1:12: missing : for identifier declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
|
||||
ParserImpl p{"var<private> my_var : f32"};
|
||||
auto v = p.variable_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("var<private> my_var : f32");
|
||||
auto v = p->variable_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(v, nullptr);
|
||||
EXPECT_EQ(v->name(), "my_var");
|
||||
EXPECT_TRUE(v->type()->IsF32());
|
||||
|
@ -63,11 +62,11 @@ TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecl_InvalidStorageClass) {
|
||||
ParserImpl p{"var<unknown> my_var : f32"};
|
||||
auto v = p.variable_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("var<unknown> my_var : f32");
|
||||
auto v = p->variable_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(v, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:5: invalid storage class for variable decoration");
|
||||
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable decoration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -16,17 +16,16 @@
|
|||
#include "src/ast/builtin_decoration.h"
|
||||
#include "src/ast/location_decoration.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecorationList_Parses) {
|
||||
ParserImpl p{R"([[location 4, builtin position]])"};
|
||||
auto decos = p.variable_decoration_list();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser(R"([[location 4, builtin position]])");
|
||||
auto decos = p->variable_decoration_list();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_EQ(decos.size(), 2);
|
||||
ASSERT_TRUE(decos[0]->IsLocation());
|
||||
EXPECT_EQ(decos[0]->AsLocation()->value(), 4);
|
||||
|
@ -35,45 +34,45 @@ TEST_F(ParserImplTest, VariableDecorationList_Parses) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecorationList_Empty) {
|
||||
ParserImpl p{R"([[]])"};
|
||||
auto decos = p.variable_decoration_list();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:3: empty variable decoration list");
|
||||
auto p = parser(R"([[]])");
|
||||
auto decos = p->variable_decoration_list();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:3: empty variable decoration list");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecorationList_Invalid) {
|
||||
ParserImpl p{R"([[invalid]])"};
|
||||
auto decos = p.variable_decoration_list();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:3: missing variable decoration for decoration list");
|
||||
auto p = parser(R"([[invalid]])");
|
||||
auto decos = p->variable_decoration_list();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:3: missing variable decoration for decoration list");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecorationList_ExtraComma) {
|
||||
ParserImpl p{R"([[builtin position, ]])"};
|
||||
auto decos = p.variable_decoration_list();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:21: missing variable decoration after comma");
|
||||
auto p = parser(R"([[builtin position, ]])");
|
||||
auto decos = p->variable_decoration_list();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:21: missing variable decoration after comma");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecorationList_MissingComma) {
|
||||
ParserImpl p{R"([[binding 4 location 5]])"};
|
||||
auto decos = p.variable_decoration_list();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:13: missing comma in variable decoration list");
|
||||
auto p = parser(R"([[binding 4 location 5]])");
|
||||
auto decos = p->variable_decoration_list();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:13: missing comma in variable decoration list");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecorationList_BadDecoration) {
|
||||
ParserImpl p{R"([[location bad]])"};
|
||||
auto decos = p.variable_decoration_list();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:12: invalid value for location decoration");
|
||||
auto p = parser(R"([[location bad]])");
|
||||
auto decos = p->variable_decoration_list();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:12: invalid value for location decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecorationList_InvalidBuiltin) {
|
||||
ParserImpl p{"[[builtin invalid]]"};
|
||||
auto decos = p.variable_decoration_list();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:11: invalid value for builtin decoration");
|
||||
auto p = parser("[[builtin invalid]]");
|
||||
auto decos = p->variable_decoration_list();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:11: invalid value for builtin decoration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -18,18 +18,17 @@
|
|||
#include "src/ast/location_decoration.h"
|
||||
#include "src/ast/set_decoration.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Location) {
|
||||
ParserImpl p{"location 4"};
|
||||
auto deco = p.variable_decoration();
|
||||
auto p = parser("location 4");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_NE(deco, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_TRUE(deco->IsLocation());
|
||||
|
||||
auto loc = deco->AsLocation();
|
||||
|
@ -37,25 +36,25 @@ TEST_F(ParserImplTest, VariableDecoration_Location) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Location_MissingValue) {
|
||||
ParserImpl p{"location"};
|
||||
auto deco = p.variable_decoration();
|
||||
auto p = parser("location");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_EQ(deco, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:9: invalid value for location decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:9: invalid value for location decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Location_MissingInvalid) {
|
||||
ParserImpl p{"location nan"};
|
||||
auto deco = p.variable_decoration();
|
||||
auto p = parser("location nan");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_EQ(deco, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:10: invalid value for location decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:10: invalid value for location decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Builtin) {
|
||||
ParserImpl p{"builtin frag_depth"};
|
||||
auto deco = p.variable_decoration();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("builtin frag_depth");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(deco, nullptr);
|
||||
ASSERT_TRUE(deco->IsBuiltin());
|
||||
|
||||
|
@ -64,26 +63,26 @@ TEST_F(ParserImplTest, VariableDecoration_Builtin) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingValue) {
|
||||
ParserImpl p{"builtin"};
|
||||
auto deco = p.variable_decoration();
|
||||
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");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:8: invalid value for builtin decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingInvalid) {
|
||||
ParserImpl p{"builtin 3"};
|
||||
auto deco = p.variable_decoration();
|
||||
auto p = parser("builtin 3");
|
||||
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");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:9: invalid value for builtin decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Binding) {
|
||||
ParserImpl p{"binding 4"};
|
||||
auto deco = p.variable_decoration();
|
||||
auto p = parser("binding 4");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_NE(deco, nullptr);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_TRUE(deco->IsBinding());
|
||||
|
||||
auto binding = deco->AsBinding();
|
||||
|
@ -91,25 +90,25 @@ TEST_F(ParserImplTest, VariableDecoration_Binding) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingValue) {
|
||||
ParserImpl p{"binding"};
|
||||
auto deco = p.variable_decoration();
|
||||
auto p = parser("binding");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_EQ(deco, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:8: invalid value for binding decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:8: invalid value for binding decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingInvalid) {
|
||||
ParserImpl p{"binding nan"};
|
||||
auto deco = p.variable_decoration();
|
||||
auto p = parser("binding nan");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_EQ(deco, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:9: invalid value for binding decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:9: invalid value for binding decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_set) {
|
||||
ParserImpl p{"set 4"};
|
||||
auto deco = p.variable_decoration();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto p = parser("set 4");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_NE(deco.get(), nullptr);
|
||||
ASSERT_TRUE(deco->IsSet());
|
||||
|
||||
|
@ -118,19 +117,19 @@ TEST_F(ParserImplTest, VariableDecoration_set) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Set_MissingValue) {
|
||||
ParserImpl p{"set"};
|
||||
auto deco = p.variable_decoration();
|
||||
auto p = parser("set");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_EQ(deco, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:4: invalid value for set decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:4: invalid value for set decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Set_MissingInvalid) {
|
||||
ParserImpl p{"set nan"};
|
||||
auto deco = p.variable_decoration();
|
||||
auto p = parser("set nan");
|
||||
auto deco = p->variable_decoration();
|
||||
ASSERT_EQ(deco, nullptr);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
EXPECT_EQ(p.error(), "1:5: invalid value for set decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:5: invalid value for set decoration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -14,69 +14,68 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, VariableIdentDecl_Parses) {
|
||||
ParserImpl p{"my_var : f32"};
|
||||
auto p = parser("my_var : f32");
|
||||
std::string name;
|
||||
ast::type::Type* type;
|
||||
std::tie(name, type) = p.variable_ident_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
std::tie(name, type) = p->variable_ident_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_EQ(name, "my_var");
|
||||
ASSERT_NE(type, nullptr);
|
||||
ASSERT_TRUE(type->IsF32());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableIdentDecl_MissingIdent) {
|
||||
ParserImpl p{": f32"};
|
||||
auto p = parser(": f32");
|
||||
std::string name;
|
||||
ast::type::Type* type;
|
||||
std::tie(name, type) = p.variable_ident_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
std::tie(name, type) = p->variable_ident_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_EQ(name, "");
|
||||
ASSERT_EQ(type, nullptr);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
ASSERT_TRUE(t.IsColon());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableIdentDecl_MissingColon) {
|
||||
ParserImpl p{"my_var f32"};
|
||||
auto r = p.variable_ident_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:8: missing : for identifier declaration");
|
||||
auto p = parser("my_var f32");
|
||||
auto r = p->variable_ident_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:8: missing : for identifier declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableIdentDecl_MissingType) {
|
||||
ParserImpl p{"my_var :"};
|
||||
auto r = p.variable_ident_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:9: invalid type for identifier declaration");
|
||||
auto p = parser("my_var :");
|
||||
auto r = p->variable_ident_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:9: invalid type for identifier declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableIdentDecl_InvalidIdent) {
|
||||
ParserImpl p{"123 : f32"};
|
||||
auto p = parser("123 : f32");
|
||||
std::string name;
|
||||
ast::type::Type* type;
|
||||
std::tie(name, type) = p.variable_ident_decl();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
std::tie(name, type) = p->variable_ident_decl();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
ASSERT_EQ(name, "");
|
||||
ASSERT_EQ(type, nullptr);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
ASSERT_TRUE(t.IsIntLiteral());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableIdentDecl_InvalidType) {
|
||||
ParserImpl p{"my_var : invalid"};
|
||||
auto r = p.variable_ident_decl();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:10: unknown type alias 'invalid'");
|
||||
auto p = parser("my_var : invalid");
|
||||
auto r = p->variable_ident_decl();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:10: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -16,17 +16,16 @@
|
|||
#include "src/ast/statement.h"
|
||||
#include "src/ast/variable_statement.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
|
||||
TEST_F(ParserImplTest, VariableStmt_VariableDecl) {
|
||||
ParserImpl p{"var a : i32;"};
|
||||
auto e = p.variable_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("var a : i32;");
|
||||
auto e = p->variable_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsVariable());
|
||||
ASSERT_NE(e->variable(), nullptr);
|
||||
|
@ -36,9 +35,9 @@ TEST_F(ParserImplTest, VariableStmt_VariableDecl) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStmt_VariableDecl_WithInit) {
|
||||
ParserImpl p{"var a : i32 = 1;"};
|
||||
auto e = p.variable_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("var a : i32 = 1;");
|
||||
auto e = p->variable_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsVariable());
|
||||
ASSERT_NE(e->variable(), nullptr);
|
||||
|
@ -49,59 +48,59 @@ TEST_F(ParserImplTest, VariableStmt_VariableDecl_WithInit) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStmt_VariableDecl_Invalid) {
|
||||
ParserImpl p{"var a : invalid;"};
|
||||
auto e = p.variable_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("var a : invalid;");
|
||||
auto e = p->variable_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:9: unknown type alias 'invalid'");
|
||||
EXPECT_EQ(p->error(), "1:9: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStmt_VariableDecl_InitializerInvalid) {
|
||||
ParserImpl p{"var a : i32 = if(a) {}"};
|
||||
auto e = p.variable_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("var a : i32 = if(a) {}");
|
||||
auto e = p->variable_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: missing initializer for variable declaration");
|
||||
EXPECT_EQ(p->error(), "1:15: missing initializer for variable declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStmt_Const) {
|
||||
ParserImpl p{"const a : i32 = 1"};
|
||||
auto e = p.variable_stmt();
|
||||
ASSERT_FALSE(p.has_error()) << p.error();
|
||||
auto p = parser("const a : i32 = 1");
|
||||
auto e = p->variable_stmt();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsVariable());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStmt_Const_InvalidVarIdent) {
|
||||
ParserImpl p{"const a : invalid = 1"};
|
||||
auto e = p.variable_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("const a : invalid = 1");
|
||||
auto e = p->variable_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:11: unknown type alias 'invalid'");
|
||||
EXPECT_EQ(p->error(), "1:11: unknown type alias 'invalid'");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStmt_Const_MissingEqual) {
|
||||
ParserImpl p{"const a : i32 1"};
|
||||
auto e = p.variable_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("const a : i32 1");
|
||||
auto e = p->variable_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:15: missing = for constant declaration");
|
||||
EXPECT_EQ(p->error(), "1:15: missing = for constant declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStmt_Const_MissingInitializer) {
|
||||
ParserImpl p{"const a : i32 ="};
|
||||
auto e = p.variable_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("const a : i32 =");
|
||||
auto e = p->variable_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:16: missing initializer for const declaration");
|
||||
EXPECT_EQ(p->error(), "1:16: missing initializer for const declaration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStmt_Const_InvalidInitializer) {
|
||||
ParserImpl p{"const a : i32 = if (a) {}"};
|
||||
auto e = p.variable_stmt();
|
||||
ASSERT_TRUE(p.has_error());
|
||||
auto p = parser("const a : i32 = if (a) {}");
|
||||
auto e = p->variable_stmt();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p.error(), "1:17: missing initializer for const declaration");
|
||||
EXPECT_EQ(p->error(), "1:17: missing initializer for const declaration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/storage_class.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
|
||||
using ParserImplTest = testing::Test;
|
||||
namespace {
|
||||
|
||||
struct VariableStorageData {
|
||||
const char* input;
|
||||
|
@ -30,16 +30,41 @@ inline std::ostream& operator<<(std::ostream& out, VariableStorageData data) {
|
|||
out << std::string(data.input);
|
||||
return out;
|
||||
}
|
||||
using VariableStorageTest = testing::TestWithParam<VariableStorageData>;
|
||||
|
||||
class VariableStorageTest : public testing::TestWithParam<VariableStorageData> {
|
||||
public:
|
||||
VariableStorageTest() = default;
|
||||
~VariableStorageTest() = default;
|
||||
|
||||
void SetUp() { ctx_.type_mgr = &tm_; }
|
||||
|
||||
void TearDown() {
|
||||
impl_ = nullptr;
|
||||
ctx_.type_mgr = 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_;
|
||||
TypeManager tm_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_P(VariableStorageTest, Parses) {
|
||||
auto params = GetParam();
|
||||
ParserImpl p{std::string("<") + params.input + ">"};
|
||||
auto p = parser(std::string("<") + params.input + ">");
|
||||
|
||||
auto sc = p.variable_storage_decoration();
|
||||
ASSERT_FALSE(p.has_error());
|
||||
auto sc = p->variable_storage_decoration();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(sc, params.result);
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsEof());
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
|
@ -60,37 +85,37 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
VariableStorageData{"function", ast::StorageClass::kFunction}));
|
||||
|
||||
TEST_F(ParserImplTest, VariableStorageDecoration_NoMatch) {
|
||||
ParserImpl p{"<not-a-storage-class>"};
|
||||
auto sc = p.variable_storage_decoration();
|
||||
auto p = parser("<not-a-storage-class>");
|
||||
auto sc = p->variable_storage_decoration();
|
||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:2: invalid storage class for variable decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:2: invalid storage class for variable decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStorageDecoration_Empty) {
|
||||
ParserImpl p{"<>"};
|
||||
auto sc = p.variable_storage_decoration();
|
||||
auto p = parser("<>");
|
||||
auto sc = p->variable_storage_decoration();
|
||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:2: invalid storage class for variable decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:2: invalid storage class for variable decoration");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStorageDecoration_MissingLessThan) {
|
||||
ParserImpl p{"in>"};
|
||||
auto sc = p.variable_storage_decoration();
|
||||
auto p = parser("in>");
|
||||
auto sc = p->variable_storage_decoration();
|
||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
||||
ASSERT_FALSE(p.has_error());
|
||||
ASSERT_FALSE(p->has_error());
|
||||
|
||||
auto t = p.next();
|
||||
auto t = p->next();
|
||||
ASSERT_TRUE(t.IsIn());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, VariableStorageDecoration_MissingGreaterThan) {
|
||||
ParserImpl p{"<in"};
|
||||
auto sc = p.variable_storage_decoration();
|
||||
auto p = parser("<in");
|
||||
auto sc = p->variable_storage_decoration();
|
||||
ASSERT_EQ(sc, ast::StorageClass::kNone);
|
||||
ASSERT_TRUE(p.has_error());
|
||||
ASSERT_EQ(p.error(), "1:4: missing > for variable decoration");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(p->error(), "1:4: missing > for variable decoration");
|
||||
}
|
||||
|
||||
} // namespace wgsl
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "src/reader/wgsl/parser.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/context.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
|
@ -23,12 +24,19 @@ namespace wgsl {
|
|||
using ParserTest = testing::Test;
|
||||
|
||||
TEST_F(ParserTest, Empty) {
|
||||
Parser p{""};
|
||||
TypeManager tm;
|
||||
Context ctx;
|
||||
ctx.type_mgr = &tm;
|
||||
Parser p(ctx, "");
|
||||
ASSERT_TRUE(p.Parse()) << p.error();
|
||||
}
|
||||
|
||||
TEST_F(ParserTest, DISABLED_Parses) {
|
||||
Parser p{R"(
|
||||
TypeManager tm;
|
||||
Context ctx;
|
||||
ctx.type_mgr = &tm;
|
||||
|
||||
Parser p(ctx, R"(
|
||||
import "GLSL.std.430" as glsl;
|
||||
|
||||
[[location 0]] var<out> gl_FragColor : vec4<f32>;
|
||||
|
@ -36,7 +44,7 @@ import "GLSL.std.430" as glsl;
|
|||
fn main() -> void {
|
||||
gl_FragColor = vec4<f32>(.4, .2, .3, 1);
|
||||
}
|
||||
)"};
|
||||
)");
|
||||
ASSERT_TRUE(p.Parse()) << p.error();
|
||||
|
||||
auto m = p.module();
|
||||
|
@ -46,12 +54,13 @@ fn main() -> void {
|
|||
}
|
||||
|
||||
TEST_F(ParserTest, DISABLED_HandlesError) {
|
||||
Parser p{R"(
|
||||
Context ctx;
|
||||
Parser p(ctx, R"(
|
||||
import "GLSL.std.430" as glsl;
|
||||
|
||||
fn main() -> { # missing return type
|
||||
return;
|
||||
})"};
|
||||
})");
|
||||
|
||||
ASSERT_FALSE(p.Parse());
|
||||
ASSERT_TRUE(p.has_error());
|
||||
|
|
|
@ -17,25 +17,6 @@
|
|||
#include <utility>
|
||||
|
||||
namespace tint {
|
||||
namespace {
|
||||
|
||||
TypeManager* manager_ = nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
TypeManager* TypeManager::Instance() {
|
||||
if (!manager_) {
|
||||
manager_ = new TypeManager();
|
||||
}
|
||||
return manager_;
|
||||
}
|
||||
|
||||
// static
|
||||
void TypeManager::Destroy() {
|
||||
delete manager_;
|
||||
manager_ = nullptr;
|
||||
}
|
||||
|
||||
TypeManager::TypeManager() = default;
|
||||
|
||||
|
|
|
@ -24,16 +24,10 @@
|
|||
namespace tint {
|
||||
|
||||
/// The type manager holds all the pointers to the known types.
|
||||
///
|
||||
/// Note, the type manager is a singleton. Any synchronization for the manager
|
||||
/// must be done by the caller.
|
||||
class TypeManager {
|
||||
public:
|
||||
/// @returns a pointer to the type manager
|
||||
static TypeManager* Instance();
|
||||
/// Frees the type manager and any associated types. The types should not be
|
||||
/// used after the manager is freed.
|
||||
static void Destroy();
|
||||
TypeManager();
|
||||
~TypeManager();
|
||||
|
||||
/// Get the given type from the type manager
|
||||
/// @param type The type to register
|
||||
|
@ -41,9 +35,6 @@ class TypeManager {
|
|||
ast::type::Type* Get(std::unique_ptr<ast::type::Type> type);
|
||||
|
||||
private:
|
||||
TypeManager();
|
||||
~TypeManager();
|
||||
|
||||
std::unordered_map<std::string, std::unique_ptr<ast::type::Type>> types_;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,60 +22,33 @@ namespace tint {
|
|||
|
||||
using TypeManagerTest = testing::Test;
|
||||
|
||||
TEST_F(TypeManagerTest, Singleton) {
|
||||
auto tm = TypeManager::Instance();
|
||||
ASSERT_NE(tm, nullptr);
|
||||
ASSERT_EQ(tm, TypeManager::Instance());
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(TypeManagerTest, Destroy) {
|
||||
auto tm = TypeManager::Instance();
|
||||
ASSERT_NE(tm, nullptr);
|
||||
ASSERT_EQ(tm, TypeManager::Instance());
|
||||
|
||||
TypeManager::Destroy();
|
||||
|
||||
tm = TypeManager::Instance();
|
||||
ASSERT_NE(tm, nullptr);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(TypeManagerTest, GetUnregistered) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto t = tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
TypeManager tm;
|
||||
auto t = tm.Get(std::make_unique<ast::type::I32Type>());
|
||||
ASSERT_NE(t, nullptr);
|
||||
EXPECT_TRUE(t->IsI32());
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(TypeManagerTest, GetSameTypeReturnsSamePtr) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto t = tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
TypeManager tm;
|
||||
auto t = tm.Get(std::make_unique<ast::type::I32Type>());
|
||||
ASSERT_NE(t, nullptr);
|
||||
EXPECT_TRUE(t->IsI32());
|
||||
|
||||
auto t2 = tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
auto t2 = tm.Get(std::make_unique<ast::type::I32Type>());
|
||||
EXPECT_EQ(t, t2);
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
TEST_F(TypeManagerTest, GetDifferentTypeReturnsDifferentPtr) {
|
||||
auto tm = TypeManager::Instance();
|
||||
auto t = tm->Get(std::make_unique<ast::type::I32Type>());
|
||||
TypeManager tm;
|
||||
auto t = tm.Get(std::make_unique<ast::type::I32Type>());
|
||||
ASSERT_NE(t, nullptr);
|
||||
EXPECT_TRUE(t->IsI32());
|
||||
|
||||
auto t2 = tm->Get(std::make_unique<ast::type::U32Type>());
|
||||
auto t2 = tm.Get(std::make_unique<ast::type::U32Type>());
|
||||
ASSERT_NE(t2, nullptr);
|
||||
EXPECT_NE(t, t2);
|
||||
EXPECT_TRUE(t2->IsU32());
|
||||
|
||||
TypeManager::Destroy();
|
||||
}
|
||||
|
||||
} // namespace tint
|
||||
|
|
Loading…
Reference in New Issue