wsgl parser: Add ParserImpl::Maybe<T>
And use it for the non-ParserImpl::expect_xxx() methods.
Another step towards supporting multiple error messages, as the caller can now test to see if the specific call errored, or didn't match, instead of using a global error state.
Makes reading the control flow conditionals a bit easier too.
Change-Id: Ie8627b8499ec9079167965da2a566401cd6bd903
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32102
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index b04a509..a4e4e71 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -77,6 +77,9 @@
template <typename T>
using Expect = ParserImpl::Expect<T>;
+template <typename T>
+using Maybe = ParserImpl::Maybe<T>;
+
/// Controls the maximum number of times we'll call into the const_expr function
/// from itself. This is to guard against stack overflow when there is an
/// excessive number of type constructors inside the const_expr.
@@ -217,66 +220,70 @@
auto decos = decoration_list();
- auto gv = global_variable_decl(decos);
+ // FUDGE - Abort early if we enter with an error state to avoid accumulating
+ // multiple error messages.
+ // TODO(ben-clayton) - remove this once resynchronization is implemented.
if (has_error())
return Failure::kErrored;
- if (gv != nullptr) {
+ auto gv = global_variable_decl(decos.value);
+ if (gv.errored)
+ return Failure::kErrored;
+ if (gv.matched) {
if (!expect("variable declaration", Token::Type::kSemicolon))
return Failure::kErrored;
- module_.AddGlobalVariable(std::move(gv));
+ module_.AddGlobalVariable(std::move(gv.value));
return true;
}
auto gc = global_constant_decl();
- if (has_error())
+ if (gc.errored) {
return Failure::kErrored;
-
- if (gc != nullptr) {
+ }
+ if (gc.matched) {
if (!expect("constant declaration", Token::Type::kSemicolon))
return Failure::kErrored;
- module_.AddGlobalVariable(std::move(gc));
+ module_.AddGlobalVariable(std::move(gc.value));
return true;
}
- auto* ta = type_alias();
- if (has_error())
+ auto ta = type_alias();
+ if (ta.errored)
return Failure::kErrored;
- if (ta != nullptr) {
+ if (ta.matched) {
if (!expect("type alias", Token::Type::kSemicolon))
return Failure::kErrored;
- module_.AddConstructedType(ta);
+ module_.AddConstructedType(ta.value);
return true;
}
- auto str = struct_decl(decos);
- if (has_error())
+ auto str = struct_decl(decos.value);
+ if (str.errored)
return Failure::kErrored;
- if (str != nullptr) {
+ if (str.matched) {
if (!expect("struct declaration", Token::Type::kSemicolon))
return Failure::kErrored;
- auto* type = ctx_.type_mgr().Get(std::move(str));
+ auto* type = ctx_.type_mgr().Get(std::move(str.value));
register_constructed(type->AsStruct()->name(), type);
module_.AddConstructedType(type);
return true;
}
- auto func = function_decl(decos);
- if (has_error())
+ auto func = function_decl(decos.value);
+ if (func.errored)
return Failure::kErrored;
-
- if (func != nullptr) {
- module_.AddFunction(std::move(func));
+ if (func.matched) {
+ module_.AddFunction(std::move(func.value));
return true;
}
- if (decos.size() > 0) {
+ if (decos.value.size() > 0) {
add_error(peek(), "expected declaration after decorations");
} else {
add_error(peek(), "invalid token");
@@ -287,15 +294,19 @@
// global_variable_decl
// : variable_decoration_list* variable_decl
// | variable_decoration_list* variable_decl EQUAL const_expr
-std::unique_ptr<ast::Variable> ParserImpl::global_variable_decl(
+Maybe<std::unique_ptr<ast::Variable>> ParserImpl::global_variable_decl(
ast::DecorationList& decos) {
- auto var = variable_decl();
- if (has_error() || var == nullptr)
- return nullptr;
+ auto decl = variable_decl();
+ if (decl.errored)
+ return Failure::kErrored;
+ if (!decl.matched)
+ return Failure::kNoMatch;
+
+ auto var = std::move(decl.value);
auto var_decos = cast_decorations<ast::VariableDecoration>(decos);
if (var_decos.errored)
- return nullptr;
+ return Failure::kErrored;
if (var_decos.value.size() > 0) {
auto dv = std::make_unique<ast::DecoratedVariable>(std::move(var));
@@ -306,34 +317,34 @@
if (match(Token::Type::kEqual)) {
auto expr = expect_const_expr();
if (expr.errored)
- return nullptr;
+ return Failure::kErrored;
var->set_constructor(std::move(expr.value));
}
- return var;
+ return std::move(var);
}
// global_constant_decl
// : CONST variable_ident_decl EQUAL const_expr
-std::unique_ptr<ast::Variable> ParserImpl::global_constant_decl() {
+Maybe<std::unique_ptr<ast::Variable>> ParserImpl::global_constant_decl() {
if (!match(Token::Type::kConst))
- return nullptr;
+ return Failure::kNoMatch;
const char* use = "constant declaration";
auto decl = expect_variable_ident_decl(use);
if (decl.errored)
- return nullptr;
+ return Failure::kErrored;
auto var = std::make_unique<ast::Variable>(
decl->source, decl->name, ast::StorageClass::kNone, decl->type);
var->set_is_const(true);
if (!expect(use, Token::Type::kEqual))
- return nullptr;
+ return Failure::kErrored;
auto init = expect_const_expr();
if (init.errored)
- return nullptr;
+ return Failure::kErrored;
var->set_constructor(std::move(init.value));
@@ -342,20 +353,21 @@
// variable_decl
// : VAR variable_storage_decoration? variable_ident_decl
-std::unique_ptr<ast::Variable> ParserImpl::variable_decl() {
+Maybe<std::unique_ptr<ast::Variable>> ParserImpl::variable_decl() {
if (!match(Token::Type::kVar))
- return nullptr;
+ return Failure::kNoMatch;
auto sc = variable_storage_decoration();
- if (has_error())
- return nullptr;
+ if (sc.errored)
+ return Failure::kErrored;
auto decl = expect_variable_ident_decl("variable declaration");
if (decl.errored)
- return nullptr;
+ return Failure::kErrored;
- return std::make_unique<ast::Variable>(decl->source, decl->name, sc,
- decl->type);
+ return std::make_unique<ast::Variable>(
+ decl->source, decl->name,
+ sc.matched ? sc.value : ast::StorageClass::kNone, decl->type);
}
// texture_sampler_types
@@ -364,88 +376,81 @@
// | sampled_texture_type LESS_THAN type_decl GREATER_THAN
// | multisampled_texture_type LESS_THAN type_decl GREATER_THAN
// | storage_texture_type LESS_THAN image_storage_type GREATER_THAN
-ast::type::Type* ParserImpl::texture_sampler_types() {
- auto* type = sampler_type();
- if (type != nullptr) {
+Maybe<ast::type::Type*> ParserImpl::texture_sampler_types() {
+ auto type = sampler_type();
+ if (type.matched)
return type;
- }
type = depth_texture_type();
- if (type != nullptr) {
- return type;
- }
+ if (type.matched)
+ return type.value;
auto dim = sampled_texture_type();
- if (dim != ast::type::TextureDimension::kNone) {
+ if (dim.matched) {
const char* use = "sampled texture type";
if (!expect(use, Token::Type::kLessThan))
- return nullptr;
+ return Failure::kErrored;
- auto* subtype = type_decl();
- if (has_error())
- return nullptr;
- if (subtype == nullptr) {
- add_error(peek().source(), "invalid subtype", use);
- return nullptr;
- }
+ auto subtype = type_decl();
+ if (subtype.errored)
+ return Failure::kErrored;
+ if (!subtype.matched)
+ return add_error(peek().source(), "invalid subtype", use);
if (!expect(use, Token::Type::kGreaterThan))
- return nullptr;
+ return Failure::kErrored;
- return ctx_.type_mgr().Get(
- std::make_unique<ast::type::SampledTextureType>(dim, subtype));
+ return ctx_.type_mgr().Get(std::make_unique<ast::type::SampledTextureType>(
+ dim.value, subtype.value));
}
- dim = multisampled_texture_type();
- if (dim != ast::type::TextureDimension::kNone) {
+ auto ms_dim = multisampled_texture_type();
+ if (ms_dim.matched) {
const char* use = "multisampled texture type";
if (!expect(use, Token::Type::kLessThan))
- return nullptr;
+ return Failure::kErrored;
- auto* subtype = type_decl();
- if (has_error())
- return nullptr;
- if (subtype == nullptr) {
- add_error(peek().source(), "invalid subtype", use);
- return nullptr;
- }
+ auto subtype = type_decl();
+ if (subtype.errored)
+ return Failure::kErrored;
+ if (!subtype.matched)
+ return add_error(peek().source(), "invalid subtype", use);
if (!expect(use, Token::Type::kGreaterThan))
- return nullptr;
+ return Failure::kErrored;
return ctx_.type_mgr().Get(
- std::make_unique<ast::type::MultisampledTextureType>(dim, subtype));
+ std::make_unique<ast::type::MultisampledTextureType>(ms_dim.value,
+ subtype.value));
}
- ast::type::TextureDimension storage_dim;
- ast::AccessControl access;
- std::tie(storage_dim, access) = storage_texture_type();
- if (storage_dim != ast::type::TextureDimension::kNone) {
+ auto storage = storage_texture_type();
+ if (storage.matched) {
const char* use = "storage texture type";
if (!expect(use, Token::Type::kLessThan))
- return nullptr;
+ return Failure::kErrored;
auto format = expect_image_storage_type(use);
if (format.errored)
- return nullptr;
+ return Failure::kErrored;
if (!expect(use, Token::Type::kGreaterThan))
- return nullptr;
+ return Failure::kErrored;
return ctx_.type_mgr().Get(std::make_unique<ast::type::StorageTextureType>(
- storage_dim, access, format.value));
+ storage->first, storage->second, format.value));
}
- return nullptr;
+ return Failure::kNoMatch;
}
// sampler_type
// : SAMPLER
// | SAMPLER_COMPARISON
-ast::type::Type* ParserImpl::sampler_type() {
+Maybe<ast::type::Type*> ParserImpl::sampler_type() {
if (match(Token::Type::kSampler))
return ctx_.type_mgr().Get(std::make_unique<ast::type::SamplerType>(
ast::type::SamplerKind::kSampler));
@@ -454,7 +459,7 @@
return ctx_.type_mgr().Get(std::make_unique<ast::type::SamplerType>(
ast::type::SamplerKind::kComparisonSampler));
- return nullptr;
+ return Failure::kNoMatch;
}
// sampled_texture_type
@@ -465,7 +470,7 @@
// | TEXTURE_SAMPLED_3D
// | TEXTURE_SAMPLED_CUBE
// | TEXTURE_SAMPLED_CUBE_ARRAY
-ast::type::TextureDimension ParserImpl::sampled_texture_type() {
+Maybe<ast::type::TextureDimension> ParserImpl::sampled_texture_type() {
if (match(Token::Type::kTextureSampled1d))
return ast::type::TextureDimension::k1d;
@@ -487,16 +492,16 @@
if (match(Token::Type::kTextureSampledCubeArray))
return ast::type::TextureDimension::kCubeArray;
- return ast::type::TextureDimension::kNone;
+ return Failure::kNoMatch;
}
// multisampled_texture_type
// : TEXTURE_MULTISAMPLED_2D
-ast::type::TextureDimension ParserImpl::multisampled_texture_type() {
+Maybe<ast::type::TextureDimension> ParserImpl::multisampled_texture_type() {
if (match(Token::Type::kTextureMultisampled2d))
return ast::type::TextureDimension::k2d;
- return ast::type::TextureDimension::kNone;
+ return Failure::kNoMatch;
}
// storage_texture_type
@@ -520,43 +525,57 @@
// | TEXTURE_STORAGE_WO_2D
// | TEXTURE_STORAGE_WO_2D_ARRAY
// | TEXTURE_STORAGE_WO_3D
-std::pair<ast::type::TextureDimension, ast::AccessControl>
+Maybe<std::pair<ast::type::TextureDimension, ast::AccessControl>>
ParserImpl::storage_texture_type() {
- if (match(Token::Type::kTextureStorageReadonly1d))
- return {ast::type::TextureDimension::k1d, ast::AccessControl::kReadOnly};
+ using Ret = std::pair<ast::type::TextureDimension, ast::AccessControl>;
+ if (match(Token::Type::kTextureStorageReadonly1d)) {
+ return Ret{ast::type::TextureDimension::k1d, ast::AccessControl::kReadOnly};
+ }
- if (match(Token::Type::kTextureStorageReadonly1dArray))
- return {ast::type::TextureDimension::k1dArray,
- ast::AccessControl::kReadOnly};
+ if (match(Token::Type::kTextureStorageReadonly1dArray)) {
+ return Ret{ast::type::TextureDimension::k1dArray,
+ ast::AccessControl::kReadOnly};
+ }
- if (match(Token::Type::kTextureStorageReadonly2d))
- return {ast::type::TextureDimension::k2d, ast::AccessControl::kReadOnly};
+ if (match(Token::Type::kTextureStorageReadonly2d)) {
+ return Ret{ast::type::TextureDimension::k2d, ast::AccessControl::kReadOnly};
+ }
- if (match(Token::Type::kTextureStorageReadonly2dArray))
- return {ast::type::TextureDimension::k2dArray,
- ast::AccessControl::kReadOnly};
+ if (match(Token::Type::kTextureStorageReadonly2dArray)) {
+ return Ret{ast::type::TextureDimension::k2dArray,
+ ast::AccessControl::kReadOnly};
+ }
- if (match(Token::Type::kTextureStorageReadonly3d))
- return {ast::type::TextureDimension::k3d, ast::AccessControl::kReadOnly};
+ if (match(Token::Type::kTextureStorageReadonly3d)) {
+ return Ret{ast::type::TextureDimension::k3d, ast::AccessControl::kReadOnly};
+ }
- if (match(Token::Type::kTextureStorageWriteonly1d))
- return {ast::type::TextureDimension::k1d, ast::AccessControl::kWriteOnly};
+ if (match(Token::Type::kTextureStorageWriteonly1d)) {
+ return Ret{ast::type::TextureDimension::k1d,
+ ast::AccessControl::kWriteOnly};
+ }
- if (match(Token::Type::kTextureStorageWriteonly1dArray))
- return {ast::type::TextureDimension::k1dArray,
- ast::AccessControl::kWriteOnly};
+ if (match(Token::Type::kTextureStorageWriteonly1dArray)) {
+ return Ret{ast::type::TextureDimension::k1dArray,
+ ast::AccessControl::kWriteOnly};
+ }
- if (match(Token::Type::kTextureStorageWriteonly2d))
- return {ast::type::TextureDimension::k2d, ast::AccessControl::kWriteOnly};
+ if (match(Token::Type::kTextureStorageWriteonly2d)) {
+ return Ret{ast::type::TextureDimension::k2d,
+ ast::AccessControl::kWriteOnly};
+ }
- if (match(Token::Type::kTextureStorageWriteonly2dArray))
- return {ast::type::TextureDimension::k2dArray,
- ast::AccessControl::kWriteOnly};
+ if (match(Token::Type::kTextureStorageWriteonly2dArray)) {
+ return Ret{ast::type::TextureDimension::k2dArray,
+ ast::AccessControl::kWriteOnly};
+ }
- if (match(Token::Type::kTextureStorageWriteonly3d))
- return {ast::type::TextureDimension::k3d, ast::AccessControl::kWriteOnly};
+ if (match(Token::Type::kTextureStorageWriteonly3d)) {
+ return Ret{ast::type::TextureDimension::k3d,
+ ast::AccessControl::kWriteOnly};
+ }
- return {ast::type::TextureDimension::kNone, ast::AccessControl::kReadOnly};
+ return Failure::kNoMatch;
}
// depth_texture_type
@@ -564,7 +583,7 @@
// | TEXTURE_DEPTH_2D_ARRAY
// | TEXTURE_DEPTH_CUBE
// | TEXTURE_DEPTH_CUBE_ARRAY
-ast::type::Type* ParserImpl::depth_texture_type() {
+Maybe<ast::type::Type*> ParserImpl::depth_texture_type() {
if (match(Token::Type::kTextureDepth2d))
return ctx_.type_mgr().Get(std::make_unique<ast::type::DepthTextureType>(
ast::type::TextureDimension::k2d));
@@ -581,7 +600,7 @@
return ctx_.type_mgr().Get(std::make_unique<ast::type::DepthTextureType>(
ast::type::TextureDimension::kCubeArray));
- return nullptr;
+ return Failure::kNoMatch;
}
// image_storage_type
@@ -742,42 +761,39 @@
return Failure::kErrored;
auto t = peek();
- auto* type = type_decl();
- if (has_error())
+ auto type = type_decl();
+ if (type.errored)
return Failure::kErrored;
+ if (!type.matched)
+ return add_error(t.source(), "invalid type", use);
- if (type == nullptr) {
- add_error(t.source(), "invalid type", use);
- return Failure::kErrored;
- }
-
- return TypedIdentifier{type, ident.value, ident.source};
+ return TypedIdentifier{type.value, ident.value, ident.source};
}
// variable_storage_decoration
// : LESS_THAN storage_class GREATER_THAN
-ast::StorageClass ParserImpl::variable_storage_decoration() {
+Maybe<ast::StorageClass> ParserImpl::variable_storage_decoration() {
if (!match(Token::Type::kLessThan))
- return ast::StorageClass::kNone;
+ return Failure::kNoMatch;
const char* use = "variable decoration";
auto sc = expect_storage_class(use);
if (sc.errored)
- return ast::StorageClass::kNone;
+ return Failure::kErrored;
if (!expect(use, Token::Type::kGreaterThan))
- return ast::StorageClass::kNone;
+ return Failure::kErrored;
return sc.value;
}
// type_alias
// : TYPE IDENT EQUAL type_decl
-ast::type::Type* ParserImpl::type_alias() {
+Maybe<ast::type::Type*> ParserImpl::type_alias() {
auto t = peek();
if (!t.IsType())
- return nullptr;
+ return Failure::kNoMatch;
next(); // Consume the peek
@@ -785,21 +801,19 @@
auto name = expect_ident(use);
if (name.errored)
- return nullptr;
+ return Failure::kErrored;
if (!expect(use, Token::Type::kEqual))
- return nullptr;
+ return Failure::kErrored;
- auto* type = type_decl();
- if (has_error())
- return nullptr;
- if (type == nullptr) {
- add_error(peek(), "invalid type alias");
- return nullptr;
- }
+ auto type = type_decl();
+ if (type.errored)
+ return Failure::kErrored;
+ if (!type.matched)
+ return add_error(peek(), "invalid type alias");
auto* alias = ctx_.type_mgr().Get(
- std::make_unique<ast::type::AliasType>(name.value, type));
+ std::make_unique<ast::type::AliasType>(name.value, type.value));
register_constructed(name.value, alias);
return alias->AsAlias();
@@ -829,14 +843,13 @@
// | MAT4x3 LESS_THAN type_decl GREATER_THAN
// | MAT4x4 LESS_THAN type_decl GREATER_THAN
// | texture_sampler_types
-ast::type::Type* ParserImpl::type_decl() {
+Maybe<ast::type::Type*> ParserImpl::type_decl() {
auto t = peek();
if (match(Token::Type::kIdentifier)) {
auto* ty = get_constructed(t.to_str());
- if (ty == nullptr) {
- add_error(t, "unknown constructed type '" + t.to_str() + "'");
- return nullptr;
- }
+ if (ty == nullptr)
+ return add_error(t, "unknown constructed type '" + t.to_str() + "'");
+
return ty;
}
@@ -853,40 +866,42 @@
return ctx_.type_mgr().Get(std::make_unique<ast::type::U32Type>());
if (t.IsVec2() || t.IsVec3() || t.IsVec4()) {
- return expect_type_decl_vector(t).value;
+ next(); // Consume the peek
+ return expect_type_decl_vector(t);
}
if (match(Token::Type::kPtr))
- return expect_type_decl_pointer().value;
+ return expect_type_decl_pointer();
auto decos = decoration_list();
- if (has_error())
- return nullptr;
+ if (decos.errored)
+ return Failure::kErrored;
if (match(Token::Type::kArray)) {
- auto array_decos = cast_decorations<ast::ArrayDecoration>(decos);
+ auto array_decos = cast_decorations<ast::ArrayDecoration>(decos.value);
if (array_decos.errored)
- return nullptr;
- return expect_type_decl_array(std::move(array_decos.value)).value;
+ return Failure::kErrored;
+
+ return expect_type_decl_array(std::move(array_decos.value));
}
- expect_decorations_consumed(decos);
+ if (!expect_decorations_consumed(decos.value))
+ return Failure::kErrored;
if (t.IsMat2x2() || t.IsMat2x3() || t.IsMat2x4() || t.IsMat3x2() ||
t.IsMat3x3() || t.IsMat3x4() || t.IsMat4x2() || t.IsMat4x3() ||
t.IsMat4x4()) {
- return expect_type_decl_matrix(t).value;
+ next(); // Consume the peek
+ return expect_type_decl_matrix(t);
}
- auto* texture_or_sampler = texture_sampler_types();
- if (has_error()) {
- return nullptr;
- }
- if (texture_or_sampler != nullptr) {
- return texture_or_sampler;
- }
+ auto texture_or_sampler = texture_sampler_types();
+ if (texture_or_sampler.errored)
+ return Failure::kErrored;
+ if (texture_or_sampler.matched)
+ return texture_or_sampler.value;
- return nullptr;
+ return Failure::kNoMatch;
}
Expect<ast::type::Type*> ParserImpl::expect_type_decl_pointer() {
@@ -902,22 +917,20 @@
if (!expect(use, Token::Type::kComma))
return Failure::kErrored;
- auto* subtype = type_decl();
- if (has_error())
+ auto subtype = type_decl();
+ if (subtype.errored)
return Failure::kErrored;
- if (subtype == nullptr)
+ if (!subtype.matched)
return add_error(peek().source(), "missing type", use);
if (!expect(use, Token::Type::kGreaterThan))
return Failure::kErrored;
return ctx_.type_mgr().Get(
- std::make_unique<ast::type::PointerType>(subtype, sc.value));
+ std::make_unique<ast::type::PointerType>(subtype.value, sc.value));
}
Expect<ast::type::Type*> ParserImpl::expect_type_decl_vector(Token t) {
- next(); // Consume the peek
-
uint32_t count = 2;
if (t.IsVec3())
count = 3;
@@ -929,18 +942,17 @@
if (!expect(use, Token::Type::kLessThan))
return Failure::kErrored;
- auto* subtype = type_decl();
- if (has_error())
+ auto subtype = type_decl();
+ if (subtype.errored)
return Failure::kErrored;
- if (subtype == nullptr) {
+ if (!subtype.matched)
return add_error(peek().source(), "unable to determine subtype", use);
- }
if (!expect(use, Token::Type::kGreaterThan))
return Failure::kErrored;
return ctx_.type_mgr().Get(
- std::make_unique<ast::type::VectorType>(subtype, count));
+ std::make_unique<ast::type::VectorType>(subtype.value, count));
}
Expect<ast::type::Type*> ParserImpl::expect_type_decl_array(
@@ -950,10 +962,10 @@
if (!expect(use, Token::Type::kLessThan))
return Failure::kErrored;
- auto* subtype = type_decl();
- if (has_error())
+ auto subtype = type_decl();
+ if (subtype.errored)
return Failure::kErrored;
- if (subtype == nullptr)
+ if (!subtype.matched)
return add_error(peek(), "invalid type for array declaration");
uint32_t size = 0;
@@ -967,14 +979,12 @@
if (!expect(use, Token::Type::kGreaterThan))
return Failure::kErrored;
- auto ty = std::make_unique<ast::type::ArrayType>(subtype, size);
+ auto ty = std::make_unique<ast::type::ArrayType>(subtype.value, size);
ty->set_decorations(std::move(decos));
return ctx_.type_mgr().Get(std::move(ty));
}
Expect<ast::type::Type*> ParserImpl::expect_type_decl_matrix(Token t) {
- next(); // Consume the peek
-
uint32_t rows = 2;
uint32_t columns = 2;
if (t.IsMat3x2() || t.IsMat3x3() || t.IsMat3x4()) {
@@ -988,22 +998,22 @@
columns = 4;
}
- t = next();
- if (!t.IsLessThan())
- return add_error(t, "missing < for matrix");
+ const char* use = "matrix";
- auto* subtype = type_decl();
- if (has_error())
+ if (!expect(use, Token::Type::kLessThan))
return Failure::kErrored;
- if (subtype == nullptr)
- return add_error(peek(), "unable to determine subtype for matrix");
- t = next();
- if (!t.IsGreaterThan())
- return add_error(t, "missing > for matrix");
+ auto subtype = type_decl();
+ if (subtype.errored)
+ return Failure::kErrored;
+ if (!subtype.matched)
+ return add_error(peek().source(), "unable to determine subtype", use);
+
+ if (!expect(use, Token::Type::kGreaterThan))
+ return Failure::kErrored;
return ctx_.type_mgr().Get(
- std::make_unique<ast::type::MatrixType>(subtype, rows, columns));
+ std::make_unique<ast::type::MatrixType>(subtype.value, rows, columns));
}
// storage_class
@@ -1050,25 +1060,25 @@
// struct_decl
// : struct_decoration_decl* STRUCT IDENT struct_body_decl
-std::unique_ptr<ast::type::StructType> ParserImpl::struct_decl(
+Maybe<std::unique_ptr<ast::type::StructType>> ParserImpl::struct_decl(
ast::DecorationList& decos) {
auto t = peek();
auto source = t.source();
if (!match(Token::Type::kStruct))
- return nullptr;
+ return Failure::kNoMatch;
auto struct_decos = cast_decorations<ast::StructDecoration>(decos);
if (struct_decos.errored)
- return nullptr;
+ return Failure::kErrored;
auto name = expect_ident("struct declaration");
if (name.errored)
- return nullptr;
+ return Failure::kErrored;
auto body = expect_struct_body_decl();
if (body.errored)
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::type::StructType>(
name.value,
@@ -1085,10 +1095,10 @@
while (!peek().IsBraceRight() && !peek().IsEof()) {
auto decos = decoration_list();
- if (has_error())
+ if (decos.errored)
return Failure::kErrored;
- auto mem = expect_struct_member(decos);
+ auto mem = expect_struct_member(decos.value);
if (mem.errored)
return Failure::kErrored;
@@ -1122,6 +1132,8 @@
return Failure::kErrored;
auto member_decos = cast_decorations<ast::StructMemberDecoration>(decos);
+ if (member_decos.errored)
+ return Failure::kErrored;
if (!expect("struct member", Token::Type::kSemicolon))
return Failure::kErrored;
@@ -1132,71 +1144,66 @@
// function_decl
// : function_header body_stmt
-std::unique_ptr<ast::Function> ParserImpl::function_decl(
+Maybe<std::unique_ptr<ast::Function>> ParserImpl::function_decl(
ast::DecorationList& decos) {
auto f = function_header();
- if (f == nullptr || has_error())
- return nullptr;
+ if (f.errored)
+ return Failure::kErrored;
+ if (!f.matched)
+ return Failure::kNoMatch;
auto func_decos = cast_decorations<ast::FunctionDecoration>(decos);
if (func_decos.errored)
- return nullptr;
- f->set_decorations(std::move(func_decos.value));
+ return Failure::kErrored;
+
+ f.value->set_decorations(std::move(func_decos.value));
auto body = expect_body_stmt();
if (body.errored)
- return nullptr;
+ return Failure::kErrored;
- f->set_body(std::move(body.value));
- return f;
+ f.value->set_body(std::move(body.value));
+ return std::move(f.value);
}
// function_type_decl
// : type_decl
// | VOID
-ast::type::Type* ParserImpl::function_type_decl() {
- auto t = peek();
- if (t.IsVoid()) {
- next(); // Consume the peek
+Maybe<ast::type::Type*> ParserImpl::function_type_decl() {
+ if (match(Token::Type::kVoid))
return ctx_.type_mgr().Get(std::make_unique<ast::type::VoidType>());
- }
+
return type_decl();
}
// function_header
// : FN IDENT PAREN_LEFT param_list PAREN_RIGHT ARROW function_type_decl
-std::unique_ptr<ast::Function> ParserImpl::function_header() {
+Maybe<std::unique_ptr<ast::Function>> ParserImpl::function_header() {
Source source;
if (!match(Token::Type::kFn, &source))
- return nullptr;
+ return Failure::kNoMatch;
const char* use = "function declaration";
auto name = expect_ident(use);
if (name.errored)
- return nullptr;
+ return Failure::kErrored;
auto params = expect_paren_block(use, [&] { return expect_param_list(); });
-
if (params.errored)
- return nullptr;
+ return Failure::kErrored;
- auto t = next();
- if (!t.IsArrow()) {
- add_error(t, "missing -> for function declaration");
- return nullptr;
- }
+ if (!expect(use, Token::Type::kArrow))
+ return Failure::kErrored;
- auto* type = function_type_decl();
- if (has_error())
- return nullptr;
- if (type == nullptr) {
- add_error(peek(), "unable to determine function return type");
- return nullptr;
- }
+ auto type = function_type_decl();
+ if (type.errored)
+ return Failure::kErrored;
+ if (!type.matched)
+ return add_error(peek(), "unable to determine function return type");
return std::make_unique<ast::Function>(source, name.value,
- std::move(params.value), type);
+ std::move(params.value), type.value);
}
// param_list
@@ -1274,13 +1281,12 @@
return expect_paren_block(
"", [&]() -> Expect<std::unique_ptr<ast::Expression>> {
auto expr = logical_or_expression();
- if (has_error())
+ if (expr.errored)
return Failure::kErrored;
-
- if (expr == nullptr)
+ if (!expr.matched)
return add_error(peek(), "unable to parse expression");
- return expr;
+ return std::move(expr.value);
});
}
@@ -1291,12 +1297,12 @@
for (;;) {
auto stmt = statement();
- if (has_error())
+ if (stmt.errored)
return Failure::kErrored;
- if (!stmt)
+ if (!stmt.matched)
break;
- ret->append(std::move(stmt));
+ ret->append(std::move(stmt.value));
}
return ret;
@@ -1316,84 +1322,84 @@
// | DISCARD SEMICOLON
// | assignment_stmt SEMICOLON
// | body_stmt?
-std::unique_ptr<ast::Statement> ParserImpl::statement() {
+Maybe<std::unique_ptr<ast::Statement>> ParserImpl::statement() {
while (match(Token::Type::kSemicolon)) {
// Skip empty statements
}
auto t = peek();
auto ret_stmt = return_stmt();
- if (has_error())
- return nullptr;
- if (ret_stmt != nullptr) {
+ if (ret_stmt.errored)
+ return Failure::kErrored;
+ if (ret_stmt.matched) {
if (!expect("return statement", Token::Type::kSemicolon))
- return nullptr;
+ return Failure::kErrored;
- return ret_stmt;
+ return std::move(ret_stmt.value);
}
auto stmt_if = if_stmt();
- if (has_error())
- return nullptr;
- if (stmt_if != nullptr)
- return stmt_if;
+ if (stmt_if.errored)
+ return Failure::kErrored;
+ if (stmt_if.matched)
+ return std::move(stmt_if.value);
auto sw = switch_stmt();
- if (has_error())
- return nullptr;
- if (sw != nullptr)
- return sw;
+ if (sw.errored)
+ return Failure::kErrored;
+ if (sw.matched)
+ return std::move(sw.value);
auto loop = loop_stmt();
- if (has_error())
- return nullptr;
- if (loop != nullptr)
- return loop;
+ if (loop.errored)
+ return Failure::kErrored;
+ if (loop.matched)
+ return std::move(loop.value);
auto stmt_for = for_stmt();
- if (has_error())
- return nullptr;
- if (stmt_for != nullptr)
- return stmt_for;
+ if (stmt_for.errored)
+ return Failure::kErrored;
+ if (stmt_for.matched)
+ return std::move(stmt_for.value);
auto func = func_call_stmt();
- if (has_error())
- return nullptr;
- if (func != nullptr) {
+ if (func.errored)
+ return Failure::kErrored;
+ if (func.matched) {
if (!expect("function call", Token::Type::kSemicolon))
- return nullptr;
+ return Failure::kErrored;
- return func;
+ return std::move(func.value);
}
auto var = variable_stmt();
- if (has_error())
- return nullptr;
- if (var != nullptr) {
+ if (var.errored)
+ return Failure::kErrored;
+ if (var.matched) {
if (!expect("variable declaration", Token::Type::kSemicolon))
- return nullptr;
+ return Failure::kErrored;
- return var;
+ return std::move(var.value);
}
auto b = break_stmt();
- if (has_error())
- return nullptr;
- if (b != nullptr) {
+ if (b.errored)
+ return Failure::kErrored;
+ if (b.matched) {
if (!expect("break statement", Token::Type::kSemicolon))
- return nullptr;
+ return Failure::kErrored;
- return b;
+ return std::move(b.value);
}
auto cont = continue_stmt();
- if (has_error())
- return nullptr;
- if (cont != nullptr) {
+ if (cont.errored)
+ return Failure::kErrored;
+ if (cont.matched) {
if (!expect("continue statement", Token::Type::kSemicolon))
- return nullptr;
+ return Failure::kErrored;
- return cont;
+ return std::move(cont.value);
}
if (t.IsDiscard()) {
@@ -1401,160 +1407,151 @@
next(); // Consume the peek
if (!expect("discard statement", Token::Type::kSemicolon))
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::DiscardStatement>(source);
}
auto assign = assignment_stmt();
- if (has_error())
- return nullptr;
- if (assign != nullptr) {
+ if (assign.errored)
+ return Failure::kErrored;
+ if (assign.matched) {
if (!expect("assignment statement", Token::Type::kSemicolon))
- return nullptr;
+ return Failure::kErrored;
- return assign;
+ return std::move(assign.value);
}
t = peek();
if (t.IsBraceLeft()) {
auto body = expect_body_stmt();
if (body.errored)
- return nullptr;
+ return Failure::kErrored;
return std::move(body.value);
}
- return nullptr;
+ return Failure::kNoMatch;
}
// return_stmt
// : RETURN logical_or_expression?
-std::unique_ptr<ast::ReturnStatement> ParserImpl::return_stmt() {
+Maybe<std::unique_ptr<ast::ReturnStatement>> ParserImpl::return_stmt() {
Source source;
if (!match(Token::Type::kReturn, &source))
- return nullptr;
+ return Failure::kNoMatch;
- std::unique_ptr<ast::Expression> expr = nullptr;
- if (!peek().IsSemicolon()) {
- expr = logical_or_expression();
- if (has_error())
- return nullptr;
- }
- return std::make_unique<ast::ReturnStatement>(source, std::move(expr));
+ if (peek().IsSemicolon())
+ return std::make_unique<ast::ReturnStatement>(source, nullptr);
+
+ auto expr = logical_or_expression();
+ if (expr.errored)
+ return Failure::kErrored;
+ // TODO(bclayton): Check matched?
+ return std::make_unique<ast::ReturnStatement>(source, std::move(expr.value));
}
// variable_stmt
// : variable_decl
// | variable_decl EQUAL logical_or_expression
// | CONST variable_ident_decl EQUAL logical_or_expression
-std::unique_ptr<ast::VariableDeclStatement> ParserImpl::variable_stmt() {
- auto t = peek();
- if (t.IsConst()) {
- next(); // Consume the peek
-
+Maybe<std::unique_ptr<ast::VariableDeclStatement>> ParserImpl::variable_stmt() {
+ if (match(Token::Type::kConst)) {
auto decl = expect_variable_ident_decl("constant declaration");
- if (has_error())
- return nullptr;
+ if (decl.errored)
+ return Failure::kErrored;
if (!expect("constant declaration", Token::Type::kEqual))
- return nullptr;
+ return Failure::kErrored;
auto constructor = logical_or_expression();
- if (has_error())
- return nullptr;
- if (constructor == nullptr) {
- add_error(peek(), "missing constructor for const declaration");
- return nullptr;
- }
+ if (constructor.errored)
+ return Failure::kErrored;
+ if (!constructor.matched)
+ return add_error(peek(), "missing constructor for const declaration");
auto var = std::make_unique<ast::Variable>(
decl->source, decl->name, ast::StorageClass::kNone, decl->type);
var->set_is_const(true);
- var->set_constructor(std::move(constructor));
+ var->set_constructor(std::move(constructor.value));
return std::make_unique<ast::VariableDeclStatement>(decl->source,
std::move(var));
}
auto var = variable_decl();
- if (has_error())
- return nullptr;
- if (var == nullptr)
- return nullptr;
+ if (var.errored)
+ return Failure::kErrored;
+ if (!var.matched)
+ return Failure::kNoMatch;
if (match(Token::Type::kEqual)) {
auto constructor = logical_or_expression();
- if (has_error())
- return nullptr;
- if (constructor == nullptr) {
- add_error(peek(), "missing constructor for variable declaration");
- return nullptr;
- }
- var->set_constructor(std::move(constructor));
+ if (constructor.errored)
+ return Failure::kErrored;
+ if (!constructor.matched)
+ return add_error(peek(), "missing constructor for variable declaration");
+
+ var.value->set_constructor(std::move(constructor.value));
}
- return std::make_unique<ast::VariableDeclStatement>(var->source(),
- std::move(var));
+ return std::make_unique<ast::VariableDeclStatement>(var.value->source(),
+ std::move(var.value));
}
// if_stmt
// : IF paren_rhs_stmt body_stmt elseif_stmt? else_stmt?
-std::unique_ptr<ast::IfStatement> ParserImpl::if_stmt() {
+Maybe<std::unique_ptr<ast::IfStatement>> ParserImpl::if_stmt() {
Source source;
if (!match(Token::Type::kIf, &source))
- return nullptr;
+ return Failure::kNoMatch;
auto condition = expect_paren_rhs_stmt();
if (condition.errored)
- return nullptr;
+ return Failure::kErrored;
auto body = expect_body_stmt();
if (body.errored)
- return nullptr;
+ return Failure::kErrored;
auto elseif = elseif_stmt();
- if (has_error())
- return nullptr;
+ if (elseif.errored)
+ return Failure::kErrored;
auto el = else_stmt();
- if (has_error())
- return nullptr;
+ if (el.errored)
+ return Failure::kErrored;
auto stmt = std::make_unique<ast::IfStatement>(
source, std::move(condition.value), std::move(body.value));
- if (el != nullptr) {
- elseif.push_back(std::move(el));
+ if (el.matched) {
+ elseif.value.push_back(std::move(el.value));
}
- stmt->set_else_statements(std::move(elseif));
+ stmt->set_else_statements(std::move(elseif.value));
return stmt;
}
// elseif_stmt
// : ELSE_IF paren_rhs_stmt body_stmt elseif_stmt?
-ast::ElseStatementList ParserImpl::elseif_stmt() {
- auto t = peek();
- if (!t.IsElseIf())
- return {};
+Maybe<ast::ElseStatementList> ParserImpl::elseif_stmt() {
+ Source source;
+ if (!match(Token::Type::kElseIf, &source))
+ return Failure::kNoMatch;
ast::ElseStatementList ret;
for (;;) {
- auto source = t.source();
- next(); // Consume the peek
-
auto condition = expect_paren_rhs_stmt();
if (condition.errored)
- return {};
+ return Failure::kErrored;
auto body = expect_body_stmt();
if (body.errored)
- return {};
+ return Failure::kErrored;
ret.push_back(std::make_unique<ast::ElseStatement>(
source, std::move(condition.value), std::move(body.value)));
- t = peek();
- if (!t.IsElseIf())
+ if (!match(Token::Type::kElseIf, &source))
break;
}
@@ -1563,60 +1560,58 @@
// else_stmt
// : ELSE body_stmt
-std::unique_ptr<ast::ElseStatement> ParserImpl::else_stmt() {
- auto t = peek();
- if (!t.IsElse())
- return nullptr;
-
- auto source = t.source();
- next(); // Consume the peek
+Maybe<std::unique_ptr<ast::ElseStatement>> ParserImpl::else_stmt() {
+ Source source;
+ if (!match(Token::Type::kElse, &source))
+ return Failure::kNoMatch;
auto body = expect_body_stmt();
if (body.errored)
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::ElseStatement>(source, std::move(body.value));
}
// switch_stmt
// : SWITCH paren_rhs_stmt BRACKET_LEFT switch_body+ BRACKET_RIGHT
-std::unique_ptr<ast::SwitchStatement> ParserImpl::switch_stmt() {
+Maybe<std::unique_ptr<ast::SwitchStatement>> ParserImpl::switch_stmt() {
Source source;
if (!match(Token::Type::kSwitch, &source))
- return nullptr;
+ return Failure::kNoMatch;
auto condition = expect_paren_rhs_stmt();
if (condition.errored)
- return nullptr;
+ return Failure::kErrored;
- ast::CaseStatementList body;
- bool ok = expect_brace_block_old("switch statement", [&] {
- for (;;) {
- auto stmt = switch_body();
- if (has_error())
- return false;
- if (stmt == nullptr)
- break;
+ auto body = expect_brace_block("switch statement",
+ [&]() -> Expect<ast::CaseStatementList> {
+ ast::CaseStatementList list;
+ for (;;) {
+ auto stmt = switch_body();
+ if (stmt.errored)
+ return Failure::kErrored;
+ if (!stmt.matched)
+ break;
- body.push_back(std::move(stmt));
- }
- return true;
- });
+ list.push_back(std::move(stmt.value));
+ }
+ return std::move(list);
+ });
- if (!ok)
- return nullptr;
+ if (body.errored)
+ return Failure::kErrored;
return std::make_unique<ast::SwitchStatement>(
- source, std::move(condition.value), std::move(body));
+ source, std::move(condition.value), std::move(body.value));
}
// switch_body
// : CASE case_selectors COLON BRACKET_LEFT case_body BRACKET_RIGHT
// | DEFAULT COLON BRACKET_LEFT case_body BRACKET_RIGHT
-std::unique_ptr<ast::CaseStatement> ParserImpl::switch_body() {
+Maybe<std::unique_ptr<ast::CaseStatement>> ParserImpl::switch_body() {
auto t = peek();
if (!t.IsCase() && !t.IsDefault())
- return nullptr;
+ return Failure::kNoMatch;
auto source = t.source();
next(); // Consume the peek
@@ -1625,26 +1620,25 @@
stmt->set_source(source);
if (t.IsCase()) {
auto selectors = expect_case_selectors();
- if (has_error())
- return nullptr;
- if (selectors.value.empty()) {
- add_error(peek(), "unable to parse case selectors");
- return nullptr;
- }
+ if (selectors.errored)
+ return Failure::kErrored;
+
stmt->set_selectors(std::move(selectors.value));
}
const char* use = "case statement";
if (!expect(use, Token::Type::kColon))
- return nullptr;
+ return Failure::kErrored;
- auto body = expect_brace_block_old(use, [&] { return case_body(); });
+ auto body = expect_brace_block(use, [&] { return case_body(); });
- if (body == nullptr)
- return nullptr;
+ if (body.errored)
+ return Failure::kErrored;
+ if (!body.matched)
+ return add_error(body.source, "expected case body");
- stmt->set_body(std::move(body));
+ stmt->set_body(std::move(body.value));
return stmt;
}
@@ -1657,14 +1651,14 @@
for (;;) {
auto t = peek();
auto cond = const_literal();
- if (has_error())
+ if (cond.errored)
return Failure::kErrored;
- if (cond == nullptr)
+ if (!cond.matched)
break;
- if (!cond->IsInt())
+ if (!cond.value->IsInt())
return add_error(t, "invalid case selector must be an integer value");
- std::unique_ptr<ast::IntLiteral> selector(cond.release()->AsInt());
+ std::unique_ptr<ast::IntLiteral> selector(cond.value.release()->AsInt());
selectors.push_back(std::move(selector));
}
@@ -1678,7 +1672,7 @@
// :
// | statement case_body
// | FALLTHROUGH SEMICOLON
-std::unique_ptr<ast::BlockStatement> ParserImpl::case_body() {
+Maybe<std::unique_ptr<ast::BlockStatement>> ParserImpl::case_body() {
auto ret = std::make_unique<ast::BlockStatement>();
for (;;) {
auto t = peek();
@@ -1687,19 +1681,19 @@
next(); // Consume the peek
if (!expect("fallthrough statement", Token::Type::kSemicolon))
- return nullptr;
+ return Failure::kErrored;
ret->append(std::make_unique<ast::FallthroughStatement>(source));
break;
}
auto stmt = statement();
- if (has_error())
- return {};
- if (stmt == nullptr)
+ if (stmt.errored)
+ return Failure::kErrored;
+ if (!stmt.matched)
break;
- ret->append(std::move(stmt));
+ ret->append(std::move(stmt.value));
}
return ret;
@@ -1707,23 +1701,23 @@
// loop_stmt
// : LOOP BRACKET_LEFT statements continuing_stmt? BRACKET_RIGHT
-std::unique_ptr<ast::LoopStatement> ParserImpl::loop_stmt() {
+Maybe<std::unique_ptr<ast::LoopStatement>> ParserImpl::loop_stmt() {
Source source;
if (!match(Token::Type::kLoop, &source))
- return nullptr;
+ return Failure::kNoMatch;
- return expect_brace_block_old(
- "loop", [&]() -> std::unique_ptr<ast::LoopStatement> {
+ return expect_brace_block(
+ "loop", [&]() -> Maybe<std::unique_ptr<ast::LoopStatement>> {
auto body = expect_statements();
if (body.errored)
- return nullptr;
+ return Failure::kErrored;
auto continuing = continuing_stmt();
- if (has_error())
- return nullptr;
+ if (continuing.errored)
+ return Failure::kErrored;
return std::make_unique<ast::LoopStatement>(
- source, std::move(body.value), std::move(continuing));
+ source, std::move(body.value), std::move(continuing.value));
});
}
@@ -1736,78 +1730,91 @@
ForHeader::~ForHeader() = default;
+// (variable_stmt | assignment_stmt | func_call_stmt)?
+Maybe<std::unique_ptr<ast::Statement>> ParserImpl::for_header_initializer() {
+ auto call = func_call_stmt();
+ if (call.errored)
+ return Failure::kErrored;
+ if (call.matched)
+ return std::move(call.value);
+
+ auto var = variable_stmt();
+ if (var.errored)
+ return Failure::kErrored;
+ if (var.matched)
+ return std::move(var.value);
+
+ auto assign = assignment_stmt();
+ if (assign.errored)
+ return Failure::kErrored;
+ if (assign.matched)
+ return std::move(assign.value);
+
+ return Failure::kNoMatch;
+}
+
+// (assignment_stmt | func_call_stmt)?
+Maybe<std::unique_ptr<ast::Statement>> ParserImpl::for_header_continuing() {
+ auto call_stmt = func_call_stmt();
+ if (call_stmt.errored)
+ return Failure::kErrored;
+ if (call_stmt.matched)
+ return std::move(call_stmt.value);
+
+ auto assign = assignment_stmt();
+ if (assign.errored)
+ return Failure::kErrored;
+ if (assign.matched)
+ return std::move(assign.value);
+
+ return Failure::kNoMatch;
+}
+
// for_header
// : (variable_stmt | assignment_stmt | func_call_stmt)?
// SEMICOLON
// logical_or_expression? SEMICOLON
// (assignment_stmt | func_call_stmt)?
Expect<std::unique_ptr<ForHeader>> ParserImpl::expect_for_header() {
- std::unique_ptr<ast::Statement> initializer = nullptr;
- if (initializer == nullptr) {
- initializer = func_call_stmt();
- if (has_error()) {
- return Failure::kErrored;
- }
- }
- if (initializer == nullptr) {
- initializer = variable_stmt();
- if (has_error()) {
- return Failure::kErrored;
- }
- }
- if (initializer == nullptr) {
- initializer = assignment_stmt();
- if (has_error()) {
- return Failure::kErrored;
- }
- }
+ auto initializer = for_header_initializer();
+ if (initializer.errored)
+ return Failure::kErrored;
if (!expect("initializer in for loop", Token::Type::kSemicolon))
return Failure::kErrored;
auto condition = logical_or_expression();
- if (has_error()) {
+ if (condition.errored)
return Failure::kErrored;
- }
if (!expect("condition in for loop", Token::Type::kSemicolon))
return Failure::kErrored;
- std::unique_ptr<ast::Statement> continuing = nullptr;
- if (continuing == nullptr) {
- continuing = func_call_stmt();
- if (has_error()) {
- return Failure::kErrored;
- }
- }
- if (continuing == nullptr) {
- continuing = assignment_stmt();
- if (has_error()) {
- return Failure::kErrored;
- }
- }
+ auto continuing = for_header_continuing();
+ if (continuing.errored)
+ return Failure::kErrored;
- return std::make_unique<ForHeader>(
- std::move(initializer), std::move(condition), std::move(continuing));
+ return std::make_unique<ForHeader>(std::move(initializer.value),
+ std::move(condition.value),
+ std::move(continuing.value));
}
// for_statement
// : FOR PAREN_LEFT for_header PAREN_RIGHT BRACE_LEFT statements BRACE_RIGHT
-std::unique_ptr<ast::Statement> ParserImpl::for_stmt() {
+Maybe<std::unique_ptr<ast::Statement>> ParserImpl::for_stmt() {
Source source;
if (!match(Token::Type::kFor, &source))
- return nullptr;
+ return Failure::kNoMatch;
auto header =
expect_paren_block("for loop", [&] { return expect_for_header(); });
if (header.errored)
- return nullptr;
+ return Failure::kErrored;
auto body =
expect_brace_block("for loop", [&] { return expect_statements(); });
-
if (body.errored)
- return nullptr;
+ return Failure::kErrored;
// The for statement is a syntactic sugar on top of the loop statement.
// We create corresponding nodes in ast with the exact same behaviour
@@ -1852,11 +1859,11 @@
// func_call_stmt
// : IDENT PAREN_LEFT argument_expression_list* PAREN_RIGHT
-std::unique_ptr<ast::CallStatement> ParserImpl::func_call_stmt() {
+Maybe<std::unique_ptr<ast::CallStatement>> ParserImpl::func_call_stmt() {
auto t = peek();
auto t2 = peek(1);
if (!t.IsIdentifier() || !t2.IsParenLeft())
- return nullptr;
+ return Failure::kNoMatch;
auto source = t.source();
@@ -1871,12 +1878,12 @@
if (!t.IsParenRight() && !t.IsEof()) {
auto list = expect_argument_expression_list();
if (list.errored)
- return nullptr;
+ return Failure::kErrored;
params = std::move(list.value);
}
if (!expect("call statement", Token::Type::kParenRight))
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::CallStatement>(
std::make_unique<ast::CallExpression>(
@@ -1886,31 +1893,31 @@
// break_stmt
// : BREAK
-std::unique_ptr<ast::BreakStatement> ParserImpl::break_stmt() {
+Maybe<std::unique_ptr<ast::BreakStatement>> ParserImpl::break_stmt() {
Source source;
if (!match(Token::Type::kBreak, &source))
- return nullptr;
+ return Failure::kNoMatch;
return std::make_unique<ast::BreakStatement>(source);
}
// continue_stmt
// : CONTINUE
-std::unique_ptr<ast::ContinueStatement> ParserImpl::continue_stmt() {
+Maybe<std::unique_ptr<ast::ContinueStatement>> ParserImpl::continue_stmt() {
Source source;
if (!match(Token::Type::kContinue, &source))
- return nullptr;
+ return Failure::kNoMatch;
return std::make_unique<ast::ContinueStatement>(source);
}
// continuing_stmt
// : CONTINUING body_stmt
-std::unique_ptr<ast::BlockStatement> ParserImpl::continuing_stmt() {
+Maybe<std::unique_ptr<ast::BlockStatement>> ParserImpl::continuing_stmt() {
if (!match(Token::Type::kContinuing))
return std::make_unique<ast::BlockStatement>();
- return expect_body_stmt().value;
+ return expect_body_stmt();
}
// primary_expression
@@ -1919,90 +1926,78 @@
// | const_literal
// | paren_rhs_stmt
// | BITCAST LESS_THAN type_decl GREATER_THAN paren_rhs_stmt
-std::unique_ptr<ast::Expression> ParserImpl::primary_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::primary_expression() {
auto t = peek();
auto source = t.source();
auto lit = const_literal();
- if (has_error())
- return nullptr;
- if (lit != nullptr) {
- return std::make_unique<ast::ScalarConstructorExpression>(source,
- std::move(lit));
- }
+ if (lit.errored)
+ return Failure::kErrored;
+ if (lit.matched)
+ return std::make_unique<ast::ScalarConstructorExpression>(
+ source, std::move(lit.value));
- t = peek();
if (t.IsParenLeft()) {
auto paren = expect_paren_rhs_stmt();
if (paren.errored)
- return nullptr;
+ return Failure::kErrored;
return std::move(paren.value);
}
- if (t.IsBitcast()) {
- auto src = t;
+ if (match(Token::Type::kBitcast)) {
+ const char* use = "bitcast expression";
- next(); // Consume the peek
+ if (!expect(use, Token::Type::kLessThan))
+ return Failure::kErrored;
- t = next();
- if (!t.IsLessThan()) {
- add_error(t, "missing < for bitcast expression");
- return nullptr;
- }
+ auto type = type_decl();
+ if (type.errored)
+ return Failure::kErrored;
+ if (!type.matched)
+ return add_error(peek().source(), "missing type", use);
- auto* type = type_decl();
- if (has_error())
- return nullptr;
- if (type == nullptr) {
- add_error(peek(), "missing type for bitcast expression");
- return nullptr;
- }
-
- t = next();
- if (!t.IsGreaterThan()) {
- add_error(t, "missing > for bitcast expression");
- return nullptr;
- }
+ if (!expect(use, Token::Type::kGreaterThan))
+ return Failure::kErrored;
auto params = expect_paren_rhs_stmt();
if (params.errored)
- return nullptr;
+ return Failure::kErrored;
- return std::make_unique<ast::BitcastExpression>(source, type,
+ return std::make_unique<ast::BitcastExpression>(source, type.value,
std::move(params.value));
- } else if (t.IsIdentifier()) {
- next(); // Consume the peek
-
- return std::make_unique<ast::IdentifierExpression>(source, t.to_str());
}
- auto* type = type_decl();
- if (has_error())
- return nullptr;
- if (type != nullptr) {
+ if (match(Token::Type::kIdentifier))
+ return std::make_unique<ast::IdentifierExpression>(t.source(), t.to_str());
+
+ auto type = type_decl();
+ if (type.errored)
+ return Failure::kErrored;
+ if (type.matched) {
auto expr = expect_paren_block(
"type constructor",
[&]() -> Expect<std::unique_ptr<ast::TypeConstructorExpression>> {
t = peek();
if (t.IsParenRight() || t.IsEof())
return std::make_unique<ast::TypeConstructorExpression>(
- source, type, ast::ExpressionList{});
+ source, type.value, ast::ExpressionList{});
auto params = expect_argument_expression_list();
if (params.errored)
return Failure::kErrored;
return std::make_unique<ast::TypeConstructorExpression>(
- source, type, std::move(params.value));
+ source, type.value, std::move(params.value));
});
if (expr.errored)
- return nullptr;
+ return Failure::kErrored;
return std::move(expr.value);
}
- return nullptr;
+
+ return Failure::kNoMatch;
}
// postfix_expr
@@ -2010,98 +2005,88 @@
// | BRACE_LEFT logical_or_expression BRACE_RIGHT postfix_expr
// | PAREN_LEFT argument_expression_list* PAREN_RIGHT postfix_expr
// | PERIOD IDENTIFIER postfix_expr
-std::unique_ptr<ast::Expression> ParserImpl::postfix_expr(
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::postfix_expr(
std::unique_ptr<ast::Expression> prefix) {
- std::unique_ptr<ast::Expression> expr = nullptr;
-
- auto t = peek();
- auto source = t.source();
- if (t.IsBracketLeft()) {
- next(); // Consume the peek
-
+ Source source;
+ if (match(Token::Type::kBracketLeft, &source)) {
auto param = logical_or_expression();
- if (has_error())
- return nullptr;
- if (param == nullptr) {
- add_error(peek(), "unable to parse expression inside []");
- return nullptr;
- }
+ if (param.errored)
+ return Failure::kErrored;
+ if (!param.matched)
+ return add_error(peek(), "unable to parse expression inside []");
- t = next();
- if (!t.IsBracketRight()) {
- add_error(t, "missing ] for array accessor");
- return nullptr;
- }
- expr = std::make_unique<ast::ArrayAccessorExpression>(
- source, std::move(prefix), std::move(param));
+ if (!expect("array accessor", Token::Type::kBracketRight))
+ return Failure::kErrored;
- } else if (t.IsParenLeft()) {
- next(); // Consume the peek
+ return postfix_expr(std::make_unique<ast::ArrayAccessorExpression>(
+ source, std::move(prefix), std::move(param.value)));
+ }
+ if (match(Token::Type::kParenLeft, &source)) {
ast::ExpressionList params;
- t = peek();
+ auto t = peek();
if (!t.IsParenRight() && !t.IsEof()) {
auto list = expect_argument_expression_list();
if (list.errored)
- return nullptr;
+ return Failure::kErrored;
params = std::move(list.value);
}
if (!expect("call expression", Token::Type::kParenRight))
- return nullptr;
+ return Failure::kErrored;
- expr = std::make_unique<ast::CallExpression>(source, std::move(prefix),
- std::move(params));
- } else if (t.IsPeriod()) {
- next(); // Consume the peek
+ return postfix_expr(std::make_unique<ast::CallExpression>(
+ source, std::move(prefix), std::move(params)));
+ }
+ if (match(Token::Type::kPeriod)) {
auto ident = expect_ident("member accessor");
if (ident.errored)
- return nullptr;
+ return Failure::kErrored;
- expr = std::make_unique<ast::MemberAccessorExpression>(
+ return postfix_expr(std::make_unique<ast::MemberAccessorExpression>(
ident.source, std::move(prefix),
- std::make_unique<ast::IdentifierExpression>(ident.source, ident.value));
- } else {
- return prefix;
+ std::make_unique<ast::IdentifierExpression>(ident.source,
+ ident.value)));
}
- return postfix_expr(std::move(expr));
+
+ return prefix;
}
// postfix_expression
// : primary_expression postfix_expr
-std::unique_ptr<ast::Expression> ParserImpl::postfix_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::postfix_expression() {
auto prefix = primary_expression();
- if (has_error())
- return nullptr;
- if (prefix == nullptr)
- return nullptr;
+ if (prefix.errored)
+ return Failure::kErrored;
+ if (!prefix.matched)
+ return Failure::kNoMatch;
- return postfix_expr(std::move(prefix));
+ return postfix_expr(std::move(prefix.value));
}
// argument_expression_list
// : (logical_or_expression COMMA)* logical_or_expression
Expect<ast::ExpressionList> ParserImpl::expect_argument_expression_list() {
auto arg = logical_or_expression();
- if (has_error())
+ if (arg.errored)
return Failure::kErrored;
- if (arg == nullptr)
+ if (!arg.matched)
return add_error(peek(), "unable to parse argument expression");
ast::ExpressionList ret;
- ret.push_back(std::move(arg));
+ ret.push_back(std::move(arg.value));
while (match(Token::Type::kComma)) {
arg = logical_or_expression();
- if (has_error())
+ if (arg.errored)
return Failure::kErrored;
- if (arg == nullptr) {
+ if (!arg.matched) {
return add_error(peek(),
"unable to parse argument expression after comma");
}
- ret.push_back(std::move(arg));
+ ret.push_back(std::move(arg.value));
}
return ret;
}
@@ -2110,7 +2095,7 @@
// : postfix_expression
// | MINUS unary_expression
// | BANG unary_expression
-std::unique_ptr<ast::Expression> ParserImpl::unary_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::unary_expression() {
auto t = peek();
auto source = t.source();
if (t.IsMinus() || t.IsBang()) {
@@ -2123,15 +2108,14 @@
op = ast::UnaryOp::kNot;
auto expr = unary_expression();
- if (has_error())
- return nullptr;
- if (expr == nullptr) {
- add_error(peek(),
- "unable to parse right side of " + name + " expression");
- return nullptr;
- }
+ if (expr.errored)
+ return Failure::kErrored;
+ if (!expr.matched)
+ return add_error(peek(),
+ "unable to parse right side of " + name + " expression");
+
return std::make_unique<ast::UnaryOpExpression>(source, op,
- std::move(expr));
+ std::move(expr.value));
}
return postfix_expression();
}
@@ -2160,26 +2144,28 @@
next(); // Consume the peek
auto rhs = unary_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr) {
+ if (!rhs.matched) {
return add_error(peek(),
"unable to parse right side of " + name + " expression");
}
+
return expect_multiplicative_expr(std::make_unique<ast::BinaryExpression>(
- source, op, std::move(lhs), std::move(rhs)));
+ source, op, std::move(lhs), std::move(rhs.value)));
}
// multiplicative_expression
// : unary_expression multiplicative_expr
-std::unique_ptr<ast::Expression> ParserImpl::multiplicative_expression() {
+Maybe<std::unique_ptr<ast::Expression>>
+ParserImpl::multiplicative_expression() {
auto lhs = unary_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_multiplicative_expr(std::move(lhs)).value;
+ return expect_multiplicative_expr(std::move(lhs.value));
}
// additive_expr
@@ -2202,24 +2188,25 @@
next(); // Consume the peek
auto rhs = multiplicative_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr)
+ if (!rhs.matched)
return add_error(peek(), "unable to parse right side of + expression");
+
return expect_additive_expr(std::make_unique<ast::BinaryExpression>(
- source, op, std::move(lhs), std::move(rhs)));
+ source, op, std::move(lhs), std::move(rhs.value)));
}
// additive_expression
// : multiplicative_expression additive_expr
-std::unique_ptr<ast::Expression> ParserImpl::additive_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::additive_expression() {
auto lhs = multiplicative_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_additive_expr(std::move(lhs)).value;
+ return expect_additive_expr(std::move(lhs.value));
}
// shift_expr
@@ -2249,26 +2236,26 @@
}
auto rhs = additive_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr) {
+ if (!rhs.matched) {
return add_error(peek(), std::string("unable to parse right side of ") +
name + " expression");
}
return expect_shift_expr(std::make_unique<ast::BinaryExpression>(
- source, op, std::move(lhs), std::move(rhs)));
-}
+ source, op, std::move(lhs), std::move(rhs.value)));
+} // namespace wgsl
// shift_expression
// : additive_expression shift_expr
-std::unique_ptr<ast::Expression> ParserImpl::shift_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::shift_expression() {
auto lhs = additive_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_shift_expr(std::move(lhs)).value;
+ return expect_shift_expr(std::move(lhs.value));
}
// relational_expr
@@ -2297,27 +2284,27 @@
next(); // Consume the peek
auto rhs = shift_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr) {
+ if (!rhs.matched) {
return add_error(peek(),
"unable to parse right side of " + name + " expression");
}
return expect_relational_expr(std::make_unique<ast::BinaryExpression>(
- source, op, std::move(lhs), std::move(rhs)));
+ source, op, std::move(lhs), std::move(rhs.value)));
}
// relational_expression
// : shift_expression relational_expr
-std::unique_ptr<ast::Expression> ParserImpl::relational_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::relational_expression() {
auto lhs = shift_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_relational_expr(std::move(lhs)).value;
+ return expect_relational_expr(std::move(lhs.value));
}
// equality_expr
@@ -2340,27 +2327,27 @@
next(); // Consume the peek
auto rhs = relational_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr) {
+ if (!rhs.matched) {
return add_error(peek(),
"unable to parse right side of " + name + " expression");
}
return expect_equality_expr(std::make_unique<ast::BinaryExpression>(
- source, op, std::move(lhs), std::move(rhs)));
+ source, op, std::move(lhs), std::move(rhs.value)));
}
// equality_expression
// : relational_expression equality_expr
-std::unique_ptr<ast::Expression> ParserImpl::equality_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::equality_expression() {
auto lhs = relational_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_equality_expr(std::move(lhs)).value;
+ return expect_equality_expr(std::move(lhs.value));
}
// and_expr
@@ -2376,25 +2363,25 @@
next(); // Consume the peek
auto rhs = equality_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr)
+ if (!rhs.matched)
return add_error(peek(), "unable to parse right side of & expression");
return expect_and_expr(std::make_unique<ast::BinaryExpression>(
- source, ast::BinaryOp::kAnd, std::move(lhs), std::move(rhs)));
+ source, ast::BinaryOp::kAnd, std::move(lhs), std::move(rhs.value)));
}
// and_expression
// : equality_expression and_expr
-std::unique_ptr<ast::Expression> ParserImpl::and_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::and_expression() {
auto lhs = equality_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_and_expr(std::move(lhs)).value;
+ return expect_and_expr(std::move(lhs.value));
}
// exclusive_or_expr
@@ -2402,33 +2389,30 @@
// | XOR and_expression exclusive_or_expr
Expect<std::unique_ptr<ast::Expression>> ParserImpl::expect_exclusive_or_expr(
std::unique_ptr<ast::Expression> lhs) {
- auto t = peek();
- if (!t.IsXor())
+ Source source;
+ if (!match(Token::Type::kXor, &source))
return lhs;
- auto source = t.source();
- next(); // Consume the peek
-
auto rhs = and_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr)
+ if (!rhs.matched)
return add_error(peek(), "unable to parse right side of ^ expression");
return expect_exclusive_or_expr(std::make_unique<ast::BinaryExpression>(
- source, ast::BinaryOp::kXor, std::move(lhs), std::move(rhs)));
+ source, ast::BinaryOp::kXor, std::move(lhs), std::move(rhs.value)));
}
// exclusive_or_expression
// : and_expression exclusive_or_expr
-std::unique_ptr<ast::Expression> ParserImpl::exclusive_or_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::exclusive_or_expression() {
auto lhs = and_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_exclusive_or_expr(std::move(lhs)).value;
+ return expect_exclusive_or_expr(std::move(lhs.value));
}
// inclusive_or_expr
@@ -2436,33 +2420,30 @@
// | OR exclusive_or_expression inclusive_or_expr
Expect<std::unique_ptr<ast::Expression>> ParserImpl::expect_inclusive_or_expr(
std::unique_ptr<ast::Expression> lhs) {
- auto t = peek();
- if (!t.IsOr())
+ Source source;
+ if (!match(Token::Type::kOr))
return lhs;
- auto source = t.source();
- next(); // Consume the peek
-
auto rhs = exclusive_or_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr)
+ if (!rhs.matched)
return add_error(peek(), "unable to parse right side of | expression");
return expect_inclusive_or_expr(std::make_unique<ast::BinaryExpression>(
- source, ast::BinaryOp::kOr, std::move(lhs), std::move(rhs)));
+ source, ast::BinaryOp::kOr, std::move(lhs), std::move(rhs.value)));
}
// inclusive_or_expression
// : exclusive_or_expression inclusive_or_expr
-std::unique_ptr<ast::Expression> ParserImpl::inclusive_or_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::inclusive_or_expression() {
auto lhs = exclusive_or_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_inclusive_or_expr(std::move(lhs)).value;
+ return expect_inclusive_or_expr(std::move(lhs.value));
}
// logical_and_expr
@@ -2478,25 +2459,26 @@
next(); // Consume the peek
auto rhs = inclusive_or_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr)
+ if (!rhs.matched)
return add_error(peek(), "unable to parse right side of && expression");
return expect_logical_and_expr(std::make_unique<ast::BinaryExpression>(
- source, ast::BinaryOp::kLogicalAnd, std::move(lhs), std::move(rhs)));
+ source, ast::BinaryOp::kLogicalAnd, std::move(lhs),
+ std::move(rhs.value)));
}
// logical_and_expression
// : inclusive_or_expression logical_and_expr
-std::unique_ptr<ast::Expression> ParserImpl::logical_and_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::logical_and_expression() {
auto lhs = inclusive_or_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_logical_and_expr(std::move(lhs)).value;
+ return expect_logical_and_expr(std::move(lhs.value));
}
// logical_or_expr
@@ -2504,63 +2486,55 @@
// | OR_OR logical_and_expression logical_or_expr
Expect<std::unique_ptr<ast::Expression>> ParserImpl::expect_logical_or_expr(
std::unique_ptr<ast::Expression> lhs) {
- auto t = peek();
- if (!t.IsOrOr())
+ Source source;
+ if (!match(Token::Type::kOrOr))
return lhs;
- auto source = t.source();
- next(); // Consume the peek
-
auto rhs = logical_and_expression();
- if (has_error())
+ if (rhs.errored)
return Failure::kErrored;
- if (rhs == nullptr)
+ if (!rhs.matched)
return add_error(peek(), "unable to parse right side of || expression");
return expect_logical_or_expr(std::make_unique<ast::BinaryExpression>(
- source, ast::BinaryOp::kLogicalOr, std::move(lhs), std::move(rhs)));
+ source, ast::BinaryOp::kLogicalOr, std::move(lhs), std::move(rhs.value)));
}
// logical_or_expression
// : logical_and_expression logical_or_expr
-std::unique_ptr<ast::Expression> ParserImpl::logical_or_expression() {
+Maybe<std::unique_ptr<ast::Expression>> ParserImpl::logical_or_expression() {
auto lhs = logical_and_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- return expect_logical_or_expr(std::move(lhs)).value;
+ return expect_logical_or_expr(std::move(lhs.value));
}
// assignment_stmt
// : unary_expression EQUAL logical_or_expression
-std::unique_ptr<ast::AssignmentStatement> ParserImpl::assignment_stmt() {
+Maybe<std::unique_ptr<ast::AssignmentStatement>> ParserImpl::assignment_stmt() {
auto t = peek();
auto source = t.source();
auto lhs = unary_expression();
- if (has_error())
- return nullptr;
- if (lhs == nullptr)
- return nullptr;
+ if (lhs.errored)
+ return Failure::kErrored;
+ if (!lhs.matched)
+ return Failure::kNoMatch;
- t = next();
- if (!t.IsEqual()) {
- add_error(t, "missing = for assignment");
- return nullptr;
- }
+ if (!expect("assignment", Token::Type::kEqual))
+ return Failure::kErrored;
auto rhs = logical_or_expression();
- if (has_error())
- return nullptr;
- if (rhs == nullptr) {
- add_error(peek(), "unable to parse right side of assignment");
- return nullptr;
- }
+ if (rhs.errored)
+ return Failure::kErrored;
+ if (!rhs.matched)
+ return add_error(peek(), "unable to parse right side of assignment");
- return std::make_unique<ast::AssignmentStatement>(source, std::move(lhs),
- std::move(rhs));
+ return std::make_unique<ast::AssignmentStatement>(
+ source, std::move(lhs.value), std::move(rhs.value));
}
// const_literal
@@ -2569,7 +2543,7 @@
// | FLOAT_LITERAL
// | TRUE
// | FALSE
-std::unique_ptr<ast::Literal> ParserImpl::const_literal() {
+Maybe<std::unique_ptr<ast::Literal>> ParserImpl::const_literal() {
auto t = peek();
if (match(Token::Type::kTrue)) {
auto* type = ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>());
@@ -2591,7 +2565,7 @@
auto* type = ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>());
return std::make_unique<ast::FloatLiteral>(type, t.to_f32());
}
- return nullptr;
+ return Failure::kNoMatch;
}
// const_expr
@@ -2612,8 +2586,10 @@
auto source = t.source();
- auto* type = type_decl();
- if (type != nullptr) {
+ auto type = type_decl();
+ if (type.errored)
+ return Failure::kErrored;
+ if (type.matched) {
auto params = expect_paren_block(
"type constructor", [&]() -> Expect<ast::ExpressionList> {
ast::ExpressionList list;
@@ -2634,42 +2610,52 @@
return Failure::kErrored;
return std::make_unique<ast::TypeConstructorExpression>(
- source, type, std::move(params.value));
+ source, type.value, std::move(params.value));
}
auto lit = const_literal();
- if (has_error())
+ if (lit.errored)
return Failure::kErrored;
- if (lit == nullptr) {
- add_error(peek(), "unable to parse const literal");
- return Failure::kErrored;
- }
- return std::make_unique<ast::ScalarConstructorExpression>(source,
- std::move(lit));
+ if (!lit.matched)
+ return add_error(peek(), "unable to parse const literal");
+
+ return std::make_unique<ast::ScalarConstructorExpression>(
+ source, std::move(lit.value));
}
-ast::DecorationList ParserImpl::decoration_list() {
+Maybe<ast::DecorationList> ParserImpl::decoration_list() {
+ bool matched = false;
ast::DecorationList decos;
- while (decoration_bracketed_list(decos)) {
+
+ while (true) {
+ auto list = decoration_bracketed_list(decos);
+ if (list.errored)
+ return Failure::kErrored;
+ if (!list.matched)
+ break;
+
+ matched = true;
}
+
+ if (!matched)
+ return Failure::kNoMatch;
+
return decos;
}
-bool ParserImpl::decoration_bracketed_list(ast::DecorationList& decos) {
+Maybe<bool> ParserImpl::decoration_bracketed_list(ast::DecorationList& decos) {
if (!match(Token::Type::kAttrLeft)) {
- return false;
+ return Failure::kNoMatch;
}
Source source;
- if (match(Token::Type::kAttrRight, &source)) {
- add_error(source, "empty decoration list");
- return false;
- }
+ if (match(Token::Type::kAttrRight, &source))
+ return add_error(source, "empty decoration list");
while (true) {
auto deco = expect_decoration();
if (deco.errored)
- return false;
+ return Failure::kErrored;
decos.emplace_back(std::move(deco.value));
@@ -2682,87 +2668,90 @@
// e.g. [[location(1) set(2)]]
// ^^^ expected comma
expect("decoration list", Token::Type::kComma);
- return false;
+ return Failure::kErrored;
}
- return expect("decoration list", Token::Type::kAttrRight);
+ if (!expect("decoration list", Token::Type::kAttrRight))
+ return Failure::kErrored;
+
+ return true;
}
}
Expect<std::unique_ptr<ast::Decoration>> ParserImpl::expect_decoration() {
auto t = peek();
auto deco = decoration();
- if (has_error())
+ if (deco.errored)
return Failure::kErrored;
- if (deco == nullptr)
- return add_error(t, "expected decoration");
- return std::move(deco);
+ if (deco.matched)
+ return std::move(deco.value);
+ return add_error(t, "expected decoration");
}
-std::unique_ptr<ast::Decoration> ParserImpl::decoration() {
- using Result = std::unique_ptr<ast::Decoration>;
+Maybe<std::unique_ptr<ast::Decoration>> ParserImpl::decoration() {
+ using Result = Maybe<std::unique_ptr<ast::Decoration>>;
auto t = next();
if (t.IsLocation()) {
const char* use = "location decoration";
- return expect_paren_block_old(use, [&]() -> Result {
+ return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
if (val.errored)
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::LocationDecoration>(val.value, val.source);
});
}
if (t.IsBinding()) {
const char* use = "binding decoration";
- return expect_paren_block_old(use, [&]() -> Result {
+ return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
if (val.errored)
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::BindingDecoration>(val.value, val.source);
});
}
if (t.IsSet()) {
const char* use = "set decoration";
- return expect_paren_block_old(use, [&]() -> Result {
+ return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
if (val.errored)
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::SetDecoration>(val.value, val.source);
});
}
if (t.IsBuiltin()) {
- return expect_paren_block_old("builtin decoration", [&]() -> Result {
+ return expect_paren_block("builtin decoration", [&]() -> Result {
auto builtin = expect_builtin();
if (builtin.errored)
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::BuiltinDecoration>(builtin.value,
builtin.source);
});
}
if (t.IsWorkgroupSize()) {
- return expect_paren_block_old("workgroup_size decoration", [&]() -> Result {
+ return expect_paren_block("workgroup_size decoration", [&]() -> Result {
uint32_t x;
uint32_t y = 1;
uint32_t z = 1;
auto val = expect_nonzero_positive_sint("workgroup_size x parameter");
if (val.errored)
- return nullptr;
+ return Failure::kErrored;
x = val.value;
if (match(Token::Type::kComma)) {
val = expect_nonzero_positive_sint("workgroup_size y parameter");
if (val.errored)
- return nullptr;
+ return Failure::kErrored;
y = val.value;
if (match(Token::Type::kComma)) {
val = expect_nonzero_positive_sint("workgroup_size z parameter");
if (val.errored)
- return nullptr;
+ return Failure::kErrored;
z = val.value;
}
}
@@ -2771,10 +2760,10 @@
});
}
if (t.IsStage()) {
- return expect_paren_block_old("stage decoration", [&]() -> Result {
+ return expect_paren_block("stage decoration", [&]() -> Result {
auto stage = expect_pipeline_stage();
if (stage.errored)
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::StageDecoration>(stage.value, stage.source);
});
@@ -2784,26 +2773,26 @@
}
if (t.IsStride()) {
const char* use = "stride decoration";
- return expect_paren_block_old(use, [&]() -> Result {
+ return expect_paren_block(use, [&]() -> Result {
auto val = expect_nonzero_positive_sint(use);
if (val.errored)
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::StrideDecoration>(val.value, t.source());
});
}
if (t.IsOffset()) {
const char* use = "offset decoration";
- return expect_paren_block_old(use, [&]() -> Result {
+ return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
if (val.errored)
- return nullptr;
+ return Failure::kErrored;
return std::make_unique<ast::StructMemberOffsetDecoration>(val.value,
t.source());
});
}
- return nullptr;
+ return Failure::kNoMatch;
}
template <typename T>
@@ -2909,24 +2898,6 @@
}
template <typename F, typename T>
-T ParserImpl::expect_block_old(Token::Type start,
- Token::Type end,
- const std::string& use,
- F&& body) {
- if (!expect(use, start)) {
- return {};
- }
- auto res = body();
- if (has_error()) {
- return {};
- }
- if (!expect(use, end)) {
- return {};
- }
- return res;
-}
-
-template <typename F, typename T>
T ParserImpl::expect_block(Token::Type start,
Token::Type end,
const std::string& use,
@@ -2945,18 +2916,6 @@
}
template <typename F, typename T>
-T ParserImpl::expect_paren_block_old(const std::string& use, F&& body) {
- return expect_block_old(Token::Type::kParenLeft, Token::Type::kParenRight,
- use, std::forward<F>(body));
-}
-
-template <typename F, typename T>
-T ParserImpl::expect_brace_block_old(const std::string& use, F&& body) {
- return expect_block_old(Token::Type::kBraceLeft, Token::Type::kBraceRight,
- use, std::forward<F>(body));
-}
-
-template <typename F, typename T>
T ParserImpl::expect_paren_block(const std::string& use, F&& body) {
return expect_block(Token::Type::kParenLeft, Token::Type::kParenRight, use,
std::forward<F>(body));
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 5bddd68..ab3efea 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -80,10 +80,11 @@
/// ParserImpl for WGSL source data
class ParserImpl {
- /// Failure holds enumerator values used for the constructing an Expect in the
- /// errored state.
+ /// Failure holds enumerator values used for the constructing an Expect and
+ /// Match in an errored state.
struct Failure {
enum Errored { kErrored };
+ enum NoMatch { kNoMatch };
};
public:
@@ -135,6 +136,74 @@
bool errored = false;
};
+ /// Maybe is the return type of the parser methods that attempts to match a
+ /// grammar and return a parsed value of type T, or may parse part of the
+ /// grammar and then hit a parse error.
+ /// In the case of a successful grammar match, the Maybe will have |matched|
+ /// set to true.
+ /// In the case of a parse error the called method will have called
+ /// |add_error()| and the Maybe will have |errored| set to true.
+ template <typename T>
+ struct Maybe {
+ inline Maybe(std::nullptr_t) = delete; // NOLINT
+
+ /// Constructor for a successful parse.
+ /// @param val the result value of the parse
+ /// @param s the optional source of the value
+ template <typename U>
+ inline Maybe(U&& val, const Source& s = {}) // NOLINT
+ : value(std::forward<U>(val)), source(s), matched(true) {}
+
+ /// Constructor for parse error state.
+ inline Maybe(Failure::Errored) : errored(true) {} // NOLINT
+
+ /// Constructor for the no-match state.
+ inline Maybe(Failure::NoMatch) {} // NOLINT
+
+ /// Constructor from an Expect.
+ template <typename U>
+ inline Maybe(const Expect<U>& e) // NOLINT
+ : value(e.value),
+ source(e.value),
+ errored(e.errored),
+ matched(!e.errored) {}
+
+ /// Move from an Expect.
+ template <typename U>
+ inline Maybe(Expect<U>&& e) // NOLINT
+ : value(std::move(e.value)),
+ source(std::move(e.source)),
+ errored(e.errored),
+ matched(!e.errored) {}
+
+ /// Copy constructor
+ inline Maybe(const Maybe&) = default;
+ /// Move constructor
+ inline Maybe(Maybe&&) = default;
+ /// Assignment operator
+ /// @return this Maybe
+ inline Maybe& operator=(const Maybe&) = default;
+ /// Assignment move operator
+ /// @return this Maybe
+ inline Maybe& operator=(Maybe&&) = default;
+
+ /// @return a pointer to |value|. |errored| must be false to call.
+ inline T* operator->() {
+ assert(!errored);
+ return &value;
+ }
+
+ /// The value of a successful parse.
+ /// Zero-initialized when there was a parse error.
+ T value{};
+ /// Optional source of the value.
+ Source source;
+ /// True if there was a error parsing.
+ bool errored = false;
+ /// True if there was a error parsing.
+ bool matched = false;
+ };
+
/// TypedIdentifier holds a parsed identifier and type. Returned by
/// variable_ident_decl().
struct TypedIdentifier {
@@ -223,14 +292,14 @@
/// `variable_decoration_list*` provided as |decos|.
/// @returns the variable parsed or nullptr
/// @param decos the list of decorations for the variable declaration.
- std::unique_ptr<ast::Variable> global_variable_decl(
+ Maybe<std::unique_ptr<ast::Variable>> global_variable_decl(
ast::DecorationList& decos);
/// Parses a `global_constant_decl` grammar element
/// @returns the const object or nullptr
- std::unique_ptr<ast::Variable> global_constant_decl();
+ Maybe<std::unique_ptr<ast::Variable>> global_constant_decl();
/// Parses a `variable_decl` grammar element
/// @returns the parsed variable or nullptr otherwise
- std::unique_ptr<ast::Variable> variable_decl();
+ Maybe<std::unique_ptr<ast::Variable>> variable_decl();
/// Parses a `variable_ident_decl` grammar element, erroring on parse
/// failure.
/// @param use a description of what was being parsed if an error was raised.
@@ -238,13 +307,13 @@
Expect<TypedIdentifier> expect_variable_ident_decl(const std::string& use);
/// Parses a `variable_storage_decoration` grammar element
/// @returns the storage class or StorageClass::kNone if none matched
- ast::StorageClass variable_storage_decoration();
+ Maybe<ast::StorageClass> variable_storage_decoration();
/// Parses a `type_alias` grammar element
/// @returns the type alias or nullptr on error
- ast::type::Type* type_alias();
+ Maybe<ast::type::Type*> type_alias();
/// Parses a `type_decl` grammar element
/// @returns the parsed Type or nullptr if none matched.
- ast::type::Type* type_decl();
+ Maybe<ast::type::Type*> type_decl();
/// Parses a `storage_class` grammar element, erroring on parse failure.
/// @param use a description of what was being parsed if an error was raised.
/// @returns the storage class or StorageClass::kNone if none matched
@@ -253,7 +322,7 @@
/// `struct_decoration_decl*` provided as |decos|.
/// @returns the struct type or nullptr on error
/// @param decos the list of decorations for the struct declaration.
- std::unique_ptr<ast::type::StructType> struct_decl(
+ Maybe<std::unique_ptr<ast::type::StructType>> struct_decl(
ast::DecorationList& decos);
/// Parses a `struct_body_decl` grammar element, erroring on parse failure.
/// @returns the struct members
@@ -269,39 +338,40 @@
/// `function_decoration_decl*` provided as |decos|.
/// @param decos the list of decorations for the function declaration.
/// @returns the parsed function, nullptr otherwise
- std::unique_ptr<ast::Function> function_decl(ast::DecorationList& decos);
+ Maybe<std::unique_ptr<ast::Function>> function_decl(
+ ast::DecorationList& decos);
/// Parses a `texture_sampler_types` grammar element
/// @returns the parsed Type or nullptr if none matched.
- ast::type::Type* texture_sampler_types();
+ Maybe<ast::type::Type*> texture_sampler_types();
/// Parses a `sampler_type` grammar element
/// @returns the parsed Type or nullptr if none matched.
- ast::type::Type* sampler_type();
+ Maybe<ast::type::Type*> sampler_type();
/// Parses a `multisampled_texture_type` grammar element
/// @returns returns the multisample texture dimension or kNone if none
/// matched.
- ast::type::TextureDimension multisampled_texture_type();
+ Maybe<ast::type::TextureDimension> multisampled_texture_type();
/// Parses a `sampled_texture_type` grammar element
/// @returns returns the sample texture dimension or kNone if none matched.
- ast::type::TextureDimension sampled_texture_type();
+ Maybe<ast::type::TextureDimension> sampled_texture_type();
/// Parses a `storage_texture_type` grammar element
/// @returns returns the storage texture dimension and the storage access.
/// Returns kNone and kRead if none matched.
- std::pair<ast::type::TextureDimension, ast::AccessControl>
+ Maybe<std::pair<ast::type::TextureDimension, ast::AccessControl>>
storage_texture_type();
/// Parses a `depth_texture_type` grammar element
/// @returns the parsed Type or nullptr if none matched.
- ast::type::Type* depth_texture_type();
+ Maybe<ast::type::Type*> depth_texture_type();
/// Parses a `image_storage_type` grammar element
- /// @param use a description of what was being parsed if an error was raised.
+ /// @param use a description of what was being parsed if an error was raised
/// @returns returns the image format or kNone if none matched.
Expect<ast::type::ImageFormat> expect_image_storage_type(
const std::string& use);
/// Parses a `function_type_decl` grammar element
/// @returns the parsed type or nullptr otherwise
- ast::type::Type* function_type_decl();
+ Maybe<ast::type::Type*> function_type_decl();
/// Parses a `function_header` grammar element
/// @returns the parsed function nullptr otherwise
- std::unique_ptr<ast::Function> function_header();
+ Maybe<std::unique_ptr<ast::Function>> function_header();
/// Parses a `param_list` grammar element, erroring on parse failure.
/// @returns the parsed variables
Expect<ast::VariableList> expect_param_list();
@@ -324,64 +394,64 @@
Expect<std::unique_ptr<ast::BlockStatement>> expect_statements();
/// Parses a `statement` grammar element
/// @returns the parsed statement or nullptr
- std::unique_ptr<ast::Statement> statement();
+ Maybe<std::unique_ptr<ast::Statement>> statement();
/// Parses a `break_stmt` grammar element
/// @returns the parsed statement or nullptr
- std::unique_ptr<ast::BreakStatement> break_stmt();
+ Maybe<std::unique_ptr<ast::BreakStatement>> break_stmt();
/// Parses a `return_stmt` grammar element
/// @returns the parsed statement or nullptr
- std::unique_ptr<ast::ReturnStatement> return_stmt();
+ Maybe<std::unique_ptr<ast::ReturnStatement>> return_stmt();
/// Parses a `continue_stmt` grammar element
/// @returns the parsed statement or nullptr
- std::unique_ptr<ast::ContinueStatement> continue_stmt();
+ Maybe<std::unique_ptr<ast::ContinueStatement>> continue_stmt();
/// Parses a `variable_stmt` grammar element
/// @returns the parsed variable or nullptr
- std::unique_ptr<ast::VariableDeclStatement> variable_stmt();
+ Maybe<std::unique_ptr<ast::VariableDeclStatement>> variable_stmt();
/// Parses a `if_stmt` grammar element
/// @returns the parsed statement or nullptr
- std::unique_ptr<ast::IfStatement> if_stmt();
+ Maybe<std::unique_ptr<ast::IfStatement>> if_stmt();
/// Parses a `elseif_stmt` grammar element
/// @returns the parsed elements
- ast::ElseStatementList elseif_stmt();
+ Maybe<ast::ElseStatementList> elseif_stmt();
/// Parses a `else_stmt` grammar element
/// @returns the parsed statement or nullptr
- std::unique_ptr<ast::ElseStatement> else_stmt();
+ Maybe<std::unique_ptr<ast::ElseStatement>> else_stmt();
/// Parses a `switch_stmt` grammar element
/// @returns the parsed statement or nullptr
- std::unique_ptr<ast::SwitchStatement> switch_stmt();
+ Maybe<std::unique_ptr<ast::SwitchStatement>> switch_stmt();
/// Parses a `switch_body` grammar element
/// @returns the parsed statement or nullptr
- std::unique_ptr<ast::CaseStatement> switch_body();
+ Maybe<std::unique_ptr<ast::CaseStatement>> switch_body();
/// Parses a `case_selectors` grammar element
/// @returns the list of literals
Expect<ast::CaseSelectorList> expect_case_selectors();
/// Parses a `case_body` grammar element
/// @returns the parsed statements
- std::unique_ptr<ast::BlockStatement> case_body();
+ Maybe<std::unique_ptr<ast::BlockStatement>> case_body();
/// Parses a `func_call_stmt` grammar element
/// @returns the parsed function call or nullptr
- std::unique_ptr<ast::CallStatement> func_call_stmt();
+ Maybe<std::unique_ptr<ast::CallStatement>> func_call_stmt();
/// Parses a `loop_stmt` grammar element
/// @returns the parsed loop or nullptr
- std::unique_ptr<ast::LoopStatement> loop_stmt();
+ Maybe<std::unique_ptr<ast::LoopStatement>> loop_stmt();
/// Parses a `for_header` grammar element, erroring on parse failure.
/// @returns the parsed for header or nullptr
Expect<std::unique_ptr<ForHeader>> expect_for_header();
/// Parses a `for_stmt` grammar element
/// @returns the parsed for loop or nullptr
- std::unique_ptr<ast::Statement> for_stmt();
+ Maybe<std::unique_ptr<ast::Statement>> for_stmt();
/// Parses a `continuing_stmt` grammar element
/// @returns the parsed statements
- std::unique_ptr<ast::BlockStatement> continuing_stmt();
+ Maybe<std::unique_ptr<ast::BlockStatement>> continuing_stmt();
/// Parses a `const_literal` grammar element
/// @returns the const literal parsed or nullptr if none found
- std::unique_ptr<ast::Literal> const_literal();
+ Maybe<std::unique_ptr<ast::Literal>> const_literal();
/// Parses a `const_expr` grammar element, erroring on parse failure.
/// @returns the parsed constructor expression or nullptr on error
Expect<std::unique_ptr<ast::ConstructorExpression>> expect_const_expr();
/// Parses a `primary_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> primary_expression();
+ Maybe<std::unique_ptr<ast::Expression>> primary_expression();
/// Parses a `argument_expression_list` grammar element, erroring on parse
/// failure.
/// @returns the list of arguments
@@ -389,14 +459,14 @@
/// Parses the recursive portion of the postfix_expression
/// @param prefix the left side of the expression
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> postfix_expr(
+ Maybe<std::unique_ptr<ast::Expression>> postfix_expr(
std::unique_ptr<ast::Expression> prefix);
/// Parses a `postfix_expression` grammar elment
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> postfix_expression();
+ Maybe<std::unique_ptr<ast::Expression>> postfix_expression();
/// Parses a `unary_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> unary_expression();
+ Maybe<std::unique_ptr<ast::Expression>> unary_expression();
/// Parses the recursive part of the `multiplicative_expression`, erroring on
/// parse failure.
/// @param lhs the left side of the expression
@@ -405,7 +475,7 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses the `multiplicative_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> multiplicative_expression();
+ Maybe<std::unique_ptr<ast::Expression>> multiplicative_expression();
/// Parses the recursive part of the `additive_expression`, erroring on parse
/// failure.
/// @param lhs the left side of the expression
@@ -414,7 +484,7 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses the `additive_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> additive_expression();
+ Maybe<std::unique_ptr<ast::Expression>> additive_expression();
/// Parses the recursive part of the `shift_expression`, erroring on parse
/// failure.
/// @param lhs the left side of the expression
@@ -423,7 +493,7 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses the `shift_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> shift_expression();
+ Maybe<std::unique_ptr<ast::Expression>> shift_expression();
/// Parses the recursive part of the `relational_expression`, erroring on
/// parse failure.
/// @param lhs the left side of the expression
@@ -432,7 +502,7 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses the `relational_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> relational_expression();
+ Maybe<std::unique_ptr<ast::Expression>> relational_expression();
/// Parses the recursive part of the `equality_expression`, erroring on parse
/// failure.
/// @param lhs the left side of the expression
@@ -441,7 +511,7 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses the `equality_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> equality_expression();
+ Maybe<std::unique_ptr<ast::Expression>> equality_expression();
/// Parses the recursive part of the `and_expression`, erroring on parse
/// failure.
/// @param lhs the left side of the expression
@@ -450,7 +520,7 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses the `and_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> and_expression();
+ Maybe<std::unique_ptr<ast::Expression>> and_expression();
/// Parses the recursive part of the `exclusive_or_expression`, erroring on
/// parse failure.
/// @param lhs the left side of the expression
@@ -459,7 +529,7 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses the `exclusive_or_expression` grammar elememnt
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> exclusive_or_expression();
+ Maybe<std::unique_ptr<ast::Expression>> exclusive_or_expression();
/// Parses the recursive part of the `inclusive_or_expression`, erroring on
/// parse failure.
/// @param lhs the left side of the expression
@@ -468,7 +538,7 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses the `inclusive_or_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> inclusive_or_expression();
+ Maybe<std::unique_ptr<ast::Expression>> inclusive_or_expression();
/// Parses the recursive part of the `logical_and_expression`, erroring on
/// parse failure.
/// @param lhs the left side of the expression
@@ -477,7 +547,7 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses a `logical_and_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> logical_and_expression();
+ Maybe<std::unique_ptr<ast::Expression>> logical_and_expression();
/// Parses the recursive part of the `logical_or_expression`, erroring on
/// parse failure.
/// @param lhs the left side of the expression
@@ -486,18 +556,18 @@
std::unique_ptr<ast::Expression> lhs);
/// Parses a `logical_or_expression` grammar element
/// @returns the parsed expression or nullptr
- std::unique_ptr<ast::Expression> logical_or_expression();
+ Maybe<std::unique_ptr<ast::Expression>> logical_or_expression();
/// Parses a `assignment_stmt` grammar element
/// @returns the parsed assignment or nullptr
- std::unique_ptr<ast::AssignmentStatement> assignment_stmt();
+ Maybe<std::unique_ptr<ast::AssignmentStatement>> assignment_stmt();
/// Parses one or more bracketed decoration lists.
/// @return the parsed decoration list, or an empty list on error.
- ast::DecorationList decoration_list();
+ Maybe<ast::DecorationList> decoration_list();
/// Parses a list of decorations between `ATTR_LEFT` and `ATTR_RIGHT`
/// brackets.
/// @param decos the list to append newly parsed decorations to.
/// @return true if any decorations were be parsed, otherwise false.
- bool decoration_bracketed_list(ast::DecorationList& decos);
+ Maybe<bool> decoration_bracketed_list(ast::DecorationList& decos);
/// Parses a single decoration of the following types:
/// * `struct_decoration`
/// * `struct_member_decoration`
@@ -506,7 +576,7 @@
/// * `global_const_decoration`
/// * `function_decoration`
/// @return the parsed decoration, or nullptr.
- std::unique_ptr<ast::Decoration> decoration();
+ Maybe<std::unique_ptr<ast::Decoration>> decoration();
/// Parses a single decoration, reporting an error if the next token does not
/// represent a decoration.
/// @see #decoration for the full list of decorations this method parses.
@@ -568,7 +638,7 @@
/// @param body a function or lambda that is called to parse the lexical block
/// body, with the signature: `Expect<Result>()`.
/// @return the value returned by |body| if no errors are raised, otherwise
- /// a zero-initialized |T|.
+ /// an Expect with error state.
template <typename F, typename T = ReturnType<F>>
T expect_block(Token::Type start,
Token::Type end,
@@ -581,7 +651,7 @@
/// @param body a function or lambda that is called to parse the lexical block
/// body, with the signature: `Expect<Result>()`.
/// @return the value returned by |body| if no errors are raised, otherwise
- /// a zero-initialized |T|.
+ /// an Expect with error state.
template <typename F, typename T = ReturnType<F>>
T expect_paren_block(const std::string& use, F&& body);
/// A convenience function that calls |expect_block| passing
@@ -591,24 +661,10 @@
/// @param body a function or lambda that is called to parse the lexical block
/// body, with the signature: `Expect<Result>()`.
/// @return the value returned by |body| if no errors are raised, otherwise
- /// a zero-initialized |T|.
+ /// an Expect with error state.
template <typename F, typename T = ReturnType<F>>
T expect_brace_block(const std::string& use, F&& body);
- // Versions of expect_block(), expect_paren_block_old(),
- // expect_brace_block_old() that do not take an Expect for T.
- // These will be removed in the near future.
- // TODO(ben-clayton) - migrate remaining uses of these.
- template <typename F, typename T = ReturnType<F>>
- T expect_block_old(Token::Type start,
- Token::Type end,
- const std::string& use,
- F&& body);
- template <typename F, typename T = ReturnType<F>>
- T expect_paren_block_old(const std::string& use, F&& body);
- template <typename F, typename T = ReturnType<F>>
- T expect_brace_block_old(const std::string& use, F&& body);
-
/// Downcasts all the decorations in |list| to the type |T|, raising a parser
/// error if any of the decorations aren't of the type |T|.
template <typename T>
@@ -627,6 +683,9 @@
Expect<std::unique_ptr<ast::ConstructorExpression>>
expect_const_expr_internal(uint32_t depth);
+ Maybe<std::unique_ptr<ast::Statement>> for_header_initializer();
+ Maybe<std::unique_ptr<ast::Statement>> for_header_continuing();
+
Context& ctx_;
diag::List diags_;
std::unique_ptr<Lexer> lexer_;
diff --git a/src/reader/wgsl/parser_impl_additive_expression_test.cc b/src/reader/wgsl/parser_impl_additive_expression_test.cc
index a80ab60..7a93975 100644
--- a/src/reader/wgsl/parser_impl_additive_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_additive_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, AdditiveExpression_Parses_Plus) {
auto* p = parser("a + true");
auto e = p->additive_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kAdd, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,11 +51,13 @@
TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
auto* p = parser("a - true");
auto e = p->additive_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -70,24 +74,30 @@
TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {
auto* p = parser("if (a) {} + true");
auto e = p->additive_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, AdditiveExpression_InvalidRHS) {
auto* p = parser("true + if (a) {}");
auto e = p->additive_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:8: unable to parse right side of + expression");
}
TEST_F(ParserImplTest, AdditiveExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_and_expression_test.cc b/src/reader/wgsl/parser_impl_and_expression_test.cc
index 6bd1039..2b85958 100644
--- a/src/reader/wgsl/parser_impl_and_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_and_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, AndExpression_Parses) {
auto* p = parser("a & true");
auto e = p->and_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kAnd, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,24 +51,30 @@
TEST_F(ParserImplTest, AndExpression_InvalidLHS) {
auto* p = parser("if (a) {} & true");
auto e = p->and_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, AndExpression_InvalidRHS) {
auto* p = parser("true & if (a) {}");
auto e = p->and_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:8: unable to parse right side of & expression");
}
TEST_F(ParserImplTest, AndExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_assignment_stmt_test.cc b/src/reader/wgsl/parser_impl_assignment_stmt_test.cc
index fd7778f..304781e 100644
--- a/src/reader/wgsl/parser_impl_assignment_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_assignment_stmt_test.cc
@@ -31,21 +31,23 @@
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
auto* p = parser("a = 123");
auto e = p->assignment_stmt();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsAssign());
- ASSERT_NE(e->lhs(), nullptr);
- ASSERT_NE(e->rhs(), nullptr);
+ ASSERT_TRUE(e.value->IsAssign());
+ ASSERT_NE(e.value->lhs(), nullptr);
+ ASSERT_NE(e.value->rhs(), nullptr);
- ASSERT_TRUE(e->lhs()->IsIdentifier());
- auto* ident = e->lhs()->AsIdentifier();
+ ASSERT_TRUE(e.value->lhs()->IsIdentifier());
+ auto* ident = e.value->lhs()->AsIdentifier();
EXPECT_EQ(ident->name(), "a");
- ASSERT_TRUE(e->rhs()->IsConstructor());
- ASSERT_TRUE(e->rhs()->AsConstructor()->IsScalarConstructor());
+ ASSERT_TRUE(e.value->rhs()->IsConstructor());
+ ASSERT_TRUE(e.value->rhs()->AsConstructor()->IsScalarConstructor());
- auto* init = e->rhs()->AsConstructor()->AsScalarConstructor();
+ auto* init = e.value->rhs()->AsConstructor()->AsScalarConstructor();
ASSERT_NE(init->literal(), nullptr);
ASSERT_TRUE(init->literal()->IsSint());
EXPECT_EQ(init->literal()->AsSint()->value(), 123);
@@ -54,22 +56,24 @@
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
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);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsAssign());
- ASSERT_NE(e->lhs(), nullptr);
- ASSERT_NE(e->rhs(), nullptr);
+ ASSERT_TRUE(e.value->IsAssign());
+ ASSERT_NE(e.value->lhs(), nullptr);
+ ASSERT_NE(e.value->rhs(), nullptr);
- ASSERT_TRUE(e->rhs()->IsConstructor());
- ASSERT_TRUE(e->rhs()->AsConstructor()->IsScalarConstructor());
- auto* init = e->rhs()->AsConstructor()->AsScalarConstructor();
+ ASSERT_TRUE(e.value->rhs()->IsConstructor());
+ ASSERT_TRUE(e.value->rhs()->AsConstructor()->IsScalarConstructor());
+ auto* init = e.value->rhs()->AsConstructor()->AsScalarConstructor();
ASSERT_NE(init->literal(), nullptr);
ASSERT_TRUE(init->literal()->IsSint());
EXPECT_EQ(init->literal()->AsSint()->value(), 123);
- ASSERT_TRUE(e->lhs()->IsMemberAccessor());
- auto* mem = e->lhs()->AsMemberAccessor();
+ ASSERT_TRUE(e.value->lhs()->IsMemberAccessor());
+ auto* mem = e.value->lhs()->AsMemberAccessor();
ASSERT_TRUE(mem->member()->IsIdentifier());
auto* ident = mem->member()->AsIdentifier();
@@ -106,23 +110,29 @@
TEST_F(ParserImplTest, AssignmentStmt_MissingEqual) {
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_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_EQ(p->error(), "1:12: expected '=' for assignment");
}
TEST_F(ParserImplTest, AssignmentStmt_InvalidLHS) {
auto* p = parser("if (true) {} = 123");
auto e = p->assignment_stmt();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, AssignmentStmt_InvalidRHS) {
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_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:14: unable to parse right side of assignment");
}
diff --git a/src/reader/wgsl/parser_impl_break_stmt_test.cc b/src/reader/wgsl/parser_impl_break_stmt_test.cc
index 4eba159..8fd49c3 100644
--- a/src/reader/wgsl/parser_impl_break_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_break_stmt_test.cc
@@ -25,9 +25,10 @@
TEST_F(ParserImplTest, BreakStmt) {
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_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsBreak());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_call_stmt_test.cc b/src/reader/wgsl/parser_impl_call_stmt_test.cc
index 2ab8b19..ded8f50 100644
--- a/src/reader/wgsl/parser_impl_call_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_call_stmt_test.cc
@@ -28,10 +28,12 @@
auto* p = parser("a();");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ ASSERT_NE(e.value, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
- ASSERT_TRUE(e->IsCall());
- auto* c = e->AsCall()->expr();
+ ASSERT_TRUE(e.value->IsCall());
+ auto* c = e.value->AsCall()->expr();
ASSERT_TRUE(c->func()->IsIdentifier());
auto* func = c->func()->AsIdentifier();
@@ -44,10 +46,12 @@
auto* p = parser("a(1, b, 2 + 3 / b);");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ ASSERT_NE(e.value, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
- ASSERT_TRUE(e->IsCall());
- auto* c = e->AsCall()->expr();
+ ASSERT_TRUE(e.value->IsCall());
+ auto* c = e.value->AsCall()->expr();
ASSERT_TRUE(c->func()->IsIdentifier());
auto* func = c->func()->AsIdentifier();
@@ -62,21 +66,27 @@
TEST_F(ParserImplTest, Statement_Call_Missing_RightParen) {
auto* p = parser("a(");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
EXPECT_EQ(p->error(), "1:3: expected ')' for call statement");
}
TEST_F(ParserImplTest, Statement_Call_Missing_Semi) {
auto* p = parser("a()");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
EXPECT_EQ(p->error(), "1:4: expected ';' for function call");
}
TEST_F(ParserImplTest, Statement_Call_Bad_ArgList) {
auto* p = parser("a(b c);");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
EXPECT_EQ(p->error(), "1:5: expected ')' for call statement");
}
diff --git a/src/reader/wgsl/parser_impl_case_body_test.cc b/src/reader/wgsl/parser_impl_case_body_test.cc
index b878037..b840d70 100644
--- a/src/reader/wgsl/parser_impl_case_body_test.cc
+++ b/src/reader/wgsl/parser_impl_case_body_test.cc
@@ -25,7 +25,9 @@
auto* p = parser("");
auto e = p->case_body();
ASSERT_FALSE(p->has_error()) << p->error();
- EXPECT_EQ(e->size(), 0u);
+ EXPECT_FALSE(e.errored);
+ EXPECT_TRUE(e.matched);
+ EXPECT_EQ(e.value->size(), 0u);
}
TEST_F(ParserImplTest, CaseBody_Statements) {
@@ -35,31 +37,39 @@
auto e = p->case_body();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e->size(), 2u);
- EXPECT_TRUE(e->get(0)->IsVariableDecl());
- EXPECT_TRUE(e->get(1)->IsAssign());
+ EXPECT_FALSE(e.errored);
+ EXPECT_TRUE(e.matched);
+ ASSERT_EQ(e.value->size(), 2u);
+ EXPECT_TRUE(e.value->get(0)->IsVariableDecl());
+ EXPECT_TRUE(e.value->get(1)->IsAssign());
}
TEST_F(ParserImplTest, CaseBody_InvalidStatement) {
auto* p = parser("a =");
auto e = p->case_body();
- ASSERT_TRUE(p->has_error());
- EXPECT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, CaseBody_Fallthrough) {
auto* p = parser("fallthrough;");
auto e = p->case_body();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e->size(), 1u);
- EXPECT_TRUE(e->get(0)->IsFallthrough());
+ EXPECT_FALSE(e.errored);
+ EXPECT_TRUE(e.matched);
+ ASSERT_EQ(e.value->size(), 1u);
+ EXPECT_TRUE(e.value->get(0)->IsFallthrough());
}
TEST_F(ParserImplTest, CaseBody_Fallthrough_MissingSemicolon) {
auto* p = parser("fallthrough");
auto e = p->case_body();
- ASSERT_TRUE(p->has_error());
- EXPECT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:12: expected ';' for fallthrough statement");
}
diff --git a/src/reader/wgsl/parser_impl_const_literal_test.cc b/src/reader/wgsl/parser_impl_const_literal_test.cc
index 3a5420a..28b0771 100644
--- a/src/reader/wgsl/parser_impl_const_literal_test.cc
+++ b/src/reader/wgsl/parser_impl_const_literal_test.cc
@@ -28,59 +28,73 @@
TEST_F(ParserImplTest, ConstLiteral_Int) {
auto* p = parser("-234");
auto c = p->const_literal();
- ASSERT_FALSE(p->has_error());
- ASSERT_NE(c, nullptr);
- ASSERT_TRUE(c->IsSint());
- EXPECT_EQ(c->AsSint()->value(), -234);
+ EXPECT_TRUE(c.matched);
+ EXPECT_FALSE(c.errored);
+ EXPECT_FALSE(p->has_error());
+ ASSERT_NE(c.value, nullptr);
+ ASSERT_TRUE(c.value->IsSint());
+ EXPECT_EQ(c.value->AsSint()->value(), -234);
}
TEST_F(ParserImplTest, ConstLiteral_Uint) {
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);
+ EXPECT_TRUE(c.matched);
+ EXPECT_FALSE(c.errored);
+ EXPECT_FALSE(p->has_error());
+ ASSERT_NE(c.value, nullptr);
+ ASSERT_TRUE(c.value->IsUint());
+ EXPECT_EQ(c.value->AsUint()->value(), 234u);
}
TEST_F(ParserImplTest, ConstLiteral_Float) {
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(), 234e12f);
+ EXPECT_TRUE(c.matched);
+ EXPECT_FALSE(c.errored);
+ EXPECT_FALSE(p->has_error());
+ ASSERT_NE(c.value, nullptr);
+ ASSERT_TRUE(c.value->IsFloat());
+ EXPECT_FLOAT_EQ(c.value->AsFloat()->value(), 234e12f);
}
TEST_F(ParserImplTest, ConstLiteral_InvalidFloat) {
auto* p = parser("1.2e+256");
auto c = p->const_literal();
- ASSERT_EQ(c, nullptr);
+ EXPECT_FALSE(c.matched);
+ EXPECT_FALSE(c.errored);
+ ASSERT_EQ(c.value, nullptr);
}
TEST_F(ParserImplTest, ConstLiteral_True) {
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());
+ EXPECT_TRUE(c.matched);
+ EXPECT_FALSE(c.errored);
+ EXPECT_FALSE(p->has_error());
+ ASSERT_NE(c.value, nullptr);
+ ASSERT_TRUE(c.value->IsBool());
+ EXPECT_TRUE(c.value->AsBool()->IsTrue());
}
TEST_F(ParserImplTest, ConstLiteral_False) {
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());
+ EXPECT_TRUE(c.matched);
+ EXPECT_FALSE(c.errored);
+ EXPECT_FALSE(p->has_error());
+ ASSERT_NE(c.value, nullptr);
+ ASSERT_TRUE(c.value->IsBool());
+ EXPECT_TRUE(c.value->AsBool()->IsFalse());
}
TEST_F(ParserImplTest, ConstLiteral_NoMatch) {
auto* p = parser("another-token");
auto c = p->const_literal();
- ASSERT_FALSE(p->has_error());
- ASSERT_EQ(c, nullptr);
+ EXPECT_FALSE(c.matched);
+ EXPECT_FALSE(c.errored);
+ EXPECT_FALSE(p->has_error());
+ ASSERT_EQ(c.value, nullptr);
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_continue_stmt_test.cc b/src/reader/wgsl/parser_impl_continue_stmt_test.cc
index 8207e57..1a7f644 100644
--- a/src/reader/wgsl/parser_impl_continue_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_continue_stmt_test.cc
@@ -25,9 +25,10 @@
TEST_F(ParserImplTest, ContinueStmt) {
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_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsContinue());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_continuing_stmt_test.cc b/src/reader/wgsl/parser_impl_continuing_stmt_test.cc
index 9f2ab58..e29b1d4 100644
--- a/src/reader/wgsl/parser_impl_continuing_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_continuing_stmt_test.cc
@@ -24,16 +24,20 @@
TEST_F(ParserImplTest, ContinuingStmt) {
auto* p = parser("continuing { discard; }");
auto e = p->continuing_stmt();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e->size(), 1u);
- ASSERT_TRUE(e->get(0)->IsDiscard());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_EQ(e.value->size(), 1u);
+ ASSERT_TRUE(e.value->get(0)->IsDiscard());
}
TEST_F(ParserImplTest, ContinuingStmt_InvalidBody) {
auto* p = parser("continuing { discard }");
auto e = p->continuing_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:22: expected ';' for discard statement");
}
diff --git a/src/reader/wgsl/parser_impl_depth_texture_type_test.cc b/src/reader/wgsl/parser_impl_depth_texture_type_test.cc
index d86c03c..35119bb 100644
--- a/src/reader/wgsl/parser_impl_depth_texture_type_test.cc
+++ b/src/reader/wgsl/parser_impl_depth_texture_type_test.cc
@@ -24,48 +24,58 @@
TEST_F(ParserImplTest, DepthTextureType_Invalid) {
auto* p = parser("1234");
- auto* t = p->depth_texture_type();
- EXPECT_EQ(t, nullptr);
+ auto t = p->depth_texture_type();
+ EXPECT_FALSE(t.matched);
+ EXPECT_FALSE(t.errored);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, DepthTextureType_2d) {
auto* p = parser("texture_depth_2d");
- auto* t = p->depth_texture_type();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsDepth());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
+ auto t = p->depth_texture_type();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsDepth());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, DepthTextureType_2dArray) {
auto* p = parser("texture_depth_2d_array");
- auto* t = p->depth_texture_type();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsDepth());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2dArray);
+ auto t = p->depth_texture_type();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsDepth());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2dArray);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, DepthTextureType_Cube) {
auto* p = parser("texture_depth_cube");
- auto* t = p->depth_texture_type();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsDepth());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::kCube);
+ auto t = p->depth_texture_type();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsDepth());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::kCube);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, DepthTextureType_CubeArray) {
auto* p = parser("texture_depth_cube_array");
- auto* t = p->depth_texture_type();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsDepth());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::kCubeArray);
+ auto t = p->depth_texture_type();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsDepth());
+ EXPECT_EQ(t.value->AsTexture()->dim(),
+ ast::type::TextureDimension::kCubeArray);
EXPECT_FALSE(p->has_error());
}
diff --git a/src/reader/wgsl/parser_impl_else_stmt_test.cc b/src/reader/wgsl/parser_impl_else_stmt_test.cc
index f83fa4a..08313f2 100644
--- a/src/reader/wgsl/parser_impl_else_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_else_stmt_test.cc
@@ -25,26 +25,32 @@
TEST_F(ParserImplTest, ElseStmt) {
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);
- EXPECT_EQ(e->body()->size(), 2u);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsElse());
+ ASSERT_EQ(e.value->condition(), nullptr);
+ EXPECT_EQ(e.value->body()->size(), 2u);
}
TEST_F(ParserImplTest, ElseStmt_InvalidBody) {
auto* p = parser("else { fn main() -> void {}}");
auto e = p->else_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:8: expected '}'");
}
TEST_F(ParserImplTest, ElseStmt_MissingBody) {
auto* p = parser("else");
auto e = p->else_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:5: expected '{'");
}
diff --git a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
index 93ce334..dd1ae17 100644
--- a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
@@ -25,43 +25,51 @@
TEST_F(ParserImplTest, ElseIfStmt) {
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(), 1u);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_EQ(e.value.size(), 1u);
- ASSERT_TRUE(e[0]->IsElse());
- ASSERT_NE(e[0]->condition(), nullptr);
- ASSERT_TRUE(e[0]->condition()->IsBinary());
- EXPECT_EQ(e[0]->body()->size(), 2u);
+ ASSERT_TRUE(e.value[0]->IsElse());
+ ASSERT_NE(e.value[0]->condition(), nullptr);
+ ASSERT_TRUE(e.value[0]->condition()->IsBinary());
+ EXPECT_EQ(e.value[0]->body()->size(), 2u);
}
TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
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(), 2u);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_EQ(e.value.size(), 2u);
- ASSERT_TRUE(e[0]->IsElse());
- ASSERT_NE(e[0]->condition(), nullptr);
- ASSERT_TRUE(e[0]->condition()->IsBinary());
- EXPECT_EQ(e[0]->body()->size(), 2u);
+ ASSERT_TRUE(e.value[0]->IsElse());
+ ASSERT_NE(e.value[0]->condition(), nullptr);
+ ASSERT_TRUE(e.value[0]->condition()->IsBinary());
+ EXPECT_EQ(e.value[0]->body()->size(), 2u);
- ASSERT_TRUE(e[1]->IsElse());
- ASSERT_NE(e[1]->condition(), nullptr);
- ASSERT_TRUE(e[1]->condition()->IsIdentifier());
- EXPECT_EQ(e[1]->body()->size(), 1u);
+ ASSERT_TRUE(e.value[1]->IsElse());
+ ASSERT_NE(e.value[1]->condition(), nullptr);
+ ASSERT_TRUE(e.value[1]->condition()->IsIdentifier());
+ EXPECT_EQ(e.value[1]->body()->size(), 1u);
}
TEST_F(ParserImplTest, ElseIfStmt_InvalidBody) {
auto* p = parser("elseif (true) { fn main() -> void {}}");
auto e = p->elseif_stmt();
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:17: expected '}'");
}
TEST_F(ParserImplTest, ElseIfStmt_MissingBody) {
auto* p = parser("elseif (true)");
auto e = p->elseif_stmt();
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:14: expected '{'");
}
diff --git a/src/reader/wgsl/parser_impl_equality_expression_test.cc b/src/reader/wgsl/parser_impl_equality_expression_test.cc
index c3fefe1..9801d00 100644
--- a/src/reader/wgsl/parser_impl_equality_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_equality_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, EqualityExpression_Parses_Equal) {
auto* p = parser("a == true");
auto e = p->equality_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kEqual, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,11 +51,13 @@
TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
auto* p = parser("a != true");
auto e = p->equality_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kNotEqual, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -70,24 +74,30 @@
TEST_F(ParserImplTest, EqualityExpression_InvalidLHS) {
auto* p = parser("if (a) {} == true");
auto e = p->equality_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, EqualityExpression_InvalidRHS) {
auto* p = parser("true == if (a) {}");
auto e = p->equality_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: unable to parse right side of == expression");
}
TEST_F(ParserImplTest, EqualityExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_error_msg_test.cc b/src/reader/wgsl/parser_impl_error_msg_test.cc
index 222134e..08d84eb 100644
--- a/src/reader/wgsl/parser_impl_error_msg_test.cc
+++ b/src/reader/wgsl/parser_impl_error_msg_test.cc
@@ -56,21 +56,21 @@
TEST_F(ParserImplErrorTest, ArrayIndexExprMissingRBracket) {
EXPECT("fn f() -> void { x = y[1; }",
- "test.wgsl:1:25 error: missing ] for array accessor\n"
+ "test.wgsl:1:25 error: expected ']' for array accessor\n"
"fn f() -> void { x = y[1; }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, AssignmentStmtMissingAssignment) {
EXPECT("fn f() -> void { a; }",
- "test.wgsl:1:19 error: missing = for assignment\n"
+ "test.wgsl:1:19 error: expected '=' for assignment\n"
"fn f() -> void { a; }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, AssignmentStmtMissingAssignment2) {
EXPECT("fn f() -> void { a : i32; }",
- "test.wgsl:1:20 error: missing = for assignment\n"
+ "test.wgsl:1:20 error: expected '=' for assignment\n"
"fn f() -> void { a : i32; }\n"
" ^\n");
}
@@ -91,14 +91,14 @@
TEST_F(ParserImplErrorTest, BitcastExprMissingLessThan) {
EXPECT("fn f() -> void { x = bitcast(y); }",
- "test.wgsl:1:29 error: missing < for bitcast expression\n"
+ "test.wgsl:1:29 error: expected '<' for bitcast expression\n"
"fn f() -> void { x = bitcast(y); }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, BitcastExprMissingGreaterThan) {
EXPECT("fn f() -> void { x = bitcast<u32(y); }",
- "test.wgsl:1:33 error: missing > for bitcast expression\n"
+ "test.wgsl:1:33 error: expected '>' for bitcast expression\n"
"fn f() -> void { x = bitcast<u32(y); }\n"
" ^\n");
}
@@ -402,7 +402,7 @@
TEST_F(ParserImplErrorTest, FunctionDeclMissingArrow) {
EXPECT("fn f() void {}",
- "test.wgsl:1:8 error: missing -> for function declaration\n"
+ "test.wgsl:1:8 error: expected '->' for function declaration\n"
"fn f() void {}\n"
" ^^^^\n");
}
@@ -995,14 +995,14 @@
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingLessThan) {
EXPECT("var i : mat4x4;",
- "test.wgsl:1:15 error: missing < for matrix\n"
+ "test.wgsl:1:15 error: expected '<' for matrix\n"
"var i : mat4x4;\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingGreaterThan) {
EXPECT("var i : mat4x4<u32;",
- "test.wgsl:1:19 error: missing > for matrix\n"
+ "test.wgsl:1:19 error: expected '>' for matrix\n"
"var i : mat4x4<u32;\n"
" ^\n");
}
diff --git a/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc b/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
index 54d9e4c..39f34e4 100644
--- a/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, ExclusiveOrExpression_Parses) {
auto* p = parser("a ^ true");
auto e = p->exclusive_or_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kXor, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,24 +51,30 @@
TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidLHS) {
auto* p = parser("if (a) {} ^ true");
auto e = p->exclusive_or_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidRHS) {
auto* p = parser("true ^ if (a) {}");
auto e = p->exclusive_or_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:8: unable to parse right side of ^ expression");
}
TEST_F(ParserImplTest, ExclusiveOrExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_for_stmt_test.cc b/src/reader/wgsl/parser_impl_for_stmt_test.cc
index 3520a58..fe9b63f 100644
--- a/src/reader/wgsl/parser_impl_for_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_for_stmt_test.cc
@@ -161,8 +161,10 @@
auto* p_for = parser(for_str);
auto e_for = p_for->for_stmt();
- ASSERT_TRUE(p_for->has_error());
- ASSERT_EQ(e_for, nullptr);
+ EXPECT_FALSE(e_for.matched);
+ EXPECT_TRUE(e_for.errored);
+ EXPECT_TRUE(p_for->has_error());
+ ASSERT_EQ(e_for.value, nullptr);
EXPECT_EQ(p_for->error(), error_str);
}
};
diff --git a/src/reader/wgsl/parser_impl_function_decl_test.cc b/src/reader/wgsl/parser_impl_function_decl_test.cc
index 2de8075..68ba11a 100644
--- a/src/reader/wgsl/parser_impl_function_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_function_decl_test.cc
@@ -26,56 +26,64 @@
TEST_F(ParserImplTest, FunctionDecl) {
auto* p = parser("fn main(a : i32, b : f32) -> void { return; }");
- auto decorations = p->decoration_list();
- ASSERT_FALSE(p->has_error()) << p->error();
- auto f = p->function_decl(decorations);
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(f, nullptr);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ auto f = p->function_decl(decos.value);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_FALSE(f.errored);
+ EXPECT_TRUE(f.matched);
+ ASSERT_NE(f.value, nullptr);
- EXPECT_EQ(f->name(), "main");
- ASSERT_NE(f->return_type(), nullptr);
- EXPECT_TRUE(f->return_type()->IsVoid());
+ EXPECT_EQ(f.value->name(), "main");
+ ASSERT_NE(f.value->return_type(), nullptr);
+ EXPECT_TRUE(f.value->return_type()->IsVoid());
- ASSERT_EQ(f->params().size(), 2u);
- EXPECT_EQ(f->params()[0]->name(), "a");
- EXPECT_EQ(f->params()[1]->name(), "b");
+ ASSERT_EQ(f.value->params().size(), 2u);
+ EXPECT_EQ(f.value->params()[0]->name(), "a");
+ EXPECT_EQ(f.value->params()[1]->name(), "b");
- ASSERT_NE(f->return_type(), nullptr);
- EXPECT_TRUE(f->return_type()->IsVoid());
+ ASSERT_NE(f.value->return_type(), nullptr);
+ EXPECT_TRUE(f.value->return_type()->IsVoid());
- auto* body = f->body();
+ auto* body = f.value->body();
ASSERT_EQ(body->size(), 1u);
EXPECT_TRUE(body->get(0)->IsReturn());
}
TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
auto* p = parser("[[workgroup_size(2, 3, 4)]] fn main() -> void { return; }");
- auto decorations = p->decoration_list();
- ASSERT_FALSE(p->has_error()) << p->error();
- auto f = p->function_decl(decorations);
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(f, nullptr);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_FALSE(decos.errored);
+ ASSERT_TRUE(decos.matched);
+ auto f = p->function_decl(decos.value);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_FALSE(f.errored);
+ EXPECT_TRUE(f.matched);
+ ASSERT_NE(f.value, nullptr);
- EXPECT_EQ(f->name(), "main");
- ASSERT_NE(f->return_type(), nullptr);
- EXPECT_TRUE(f->return_type()->IsVoid());
- ASSERT_EQ(f->params().size(), 0u);
- ASSERT_NE(f->return_type(), nullptr);
- EXPECT_TRUE(f->return_type()->IsVoid());
+ EXPECT_EQ(f.value->name(), "main");
+ ASSERT_NE(f.value->return_type(), nullptr);
+ EXPECT_TRUE(f.value->return_type()->IsVoid());
+ ASSERT_EQ(f.value->params().size(), 0u);
+ ASSERT_NE(f.value->return_type(), nullptr);
+ EXPECT_TRUE(f.value->return_type()->IsVoid());
- auto& decos = f->decorations();
- ASSERT_EQ(decos.size(), 1u);
- ASSERT_TRUE(decos[0]->IsWorkgroup());
+ auto& decorations = f.value->decorations();
+ ASSERT_EQ(decorations.size(), 1u);
+ ASSERT_TRUE(decorations[0]->IsWorkgroup());
uint32_t x = 0;
uint32_t y = 0;
uint32_t z = 0;
- std::tie(x, y, z) = decos[0]->AsWorkgroup()->values();
+ std::tie(x, y, z) = decorations[0]->AsWorkgroup()->values();
EXPECT_EQ(x, 2u);
EXPECT_EQ(y, 3u);
EXPECT_EQ(z, 4u);
- auto* body = f->body();
+ auto* body = f.value->body();
ASSERT_EQ(body->size(), 1u);
EXPECT_TRUE(body->get(0)->IsReturn());
}
@@ -84,38 +92,42 @@
auto* p = parser(R"(
[[workgroup_size(2, 3, 4), workgroup_size(5, 6, 7)]]
fn main() -> void { return; })");
- auto decorations = p->decoration_list();
- ASSERT_FALSE(p->has_error()) << p->error();
- auto f = p->function_decl(decorations);
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(f, nullptr);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_FALSE(decos.errored);
+ ASSERT_TRUE(decos.matched);
+ auto f = p->function_decl(decos.value);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_FALSE(f.errored);
+ EXPECT_TRUE(f.matched);
+ ASSERT_NE(f.value, nullptr);
- EXPECT_EQ(f->name(), "main");
- ASSERT_NE(f->return_type(), nullptr);
- EXPECT_TRUE(f->return_type()->IsVoid());
- ASSERT_EQ(f->params().size(), 0u);
- ASSERT_NE(f->return_type(), nullptr);
- EXPECT_TRUE(f->return_type()->IsVoid());
+ EXPECT_EQ(f.value->name(), "main");
+ ASSERT_NE(f.value->return_type(), nullptr);
+ EXPECT_TRUE(f.value->return_type()->IsVoid());
+ ASSERT_EQ(f.value->params().size(), 0u);
+ ASSERT_NE(f.value->return_type(), nullptr);
+ EXPECT_TRUE(f.value->return_type()->IsVoid());
- auto& decos = f->decorations();
- ASSERT_EQ(decos.size(), 2u);
+ auto& decorations = f.value->decorations();
+ ASSERT_EQ(decorations.size(), 2u);
uint32_t x = 0;
uint32_t y = 0;
uint32_t z = 0;
- ASSERT_TRUE(decos[0]->IsWorkgroup());
- std::tie(x, y, z) = decos[0]->AsWorkgroup()->values();
+ ASSERT_TRUE(decorations[0]->IsWorkgroup());
+ std::tie(x, y, z) = decorations[0]->AsWorkgroup()->values();
EXPECT_EQ(x, 2u);
EXPECT_EQ(y, 3u);
EXPECT_EQ(z, 4u);
- ASSERT_TRUE(decos[1]->IsWorkgroup());
- std::tie(x, y, z) = decos[1]->AsWorkgroup()->values();
+ ASSERT_TRUE(decorations[1]->IsWorkgroup());
+ std::tie(x, y, z) = decorations[1]->AsWorkgroup()->values();
EXPECT_EQ(x, 5u);
EXPECT_EQ(y, 6u);
EXPECT_EQ(z, 7u);
- auto* body = f->body();
+ auto* body = f.value->body();
ASSERT_EQ(body->size(), 1u);
EXPECT_TRUE(body->get(0)->IsReturn());
}
@@ -126,19 +138,23 @@
[[workgroup_size(5, 6, 7)]]
fn main() -> void { return; })");
auto decorations = p->decoration_list();
- ASSERT_FALSE(p->has_error()) << p->error();
- auto f = p->function_decl(decorations);
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(f, nullptr);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_FALSE(decorations.errored);
+ ASSERT_TRUE(decorations.matched);
+ auto f = p->function_decl(decorations.value);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_FALSE(f.errored);
+ EXPECT_TRUE(f.matched);
+ ASSERT_NE(f.value, nullptr);
- EXPECT_EQ(f->name(), "main");
- ASSERT_NE(f->return_type(), nullptr);
- EXPECT_TRUE(f->return_type()->IsVoid());
- ASSERT_EQ(f->params().size(), 0u);
- ASSERT_NE(f->return_type(), nullptr);
- EXPECT_TRUE(f->return_type()->IsVoid());
+ EXPECT_EQ(f.value->name(), "main");
+ ASSERT_NE(f.value->return_type(), nullptr);
+ EXPECT_TRUE(f.value->return_type()->IsVoid());
+ ASSERT_EQ(f.value->params().size(), 0u);
+ ASSERT_NE(f.value->return_type(), nullptr);
+ EXPECT_TRUE(f.value->return_type()->IsVoid());
- auto& decos = f->decorations();
+ auto& decos = f.value->decorations();
ASSERT_EQ(decos.size(), 2u);
uint32_t x = 0;
@@ -156,38 +172,50 @@
EXPECT_EQ(y, 6u);
EXPECT_EQ(z, 7u);
- auto* body = f->body();
+ auto* body = f.value->body();
ASSERT_EQ(body->size(), 1u);
EXPECT_TRUE(body->get(0)->IsReturn());
}
TEST_F(ParserImplTest, FunctionDecl_InvalidHeader) {
auto* p = parser("fn main() -> { }");
- auto decorations = p->decoration_list();
- ASSERT_FALSE(p->has_error()) << p->error();
- auto f = p->function_decl(decorations);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ auto f = p->function_decl(decos.value);
+ EXPECT_TRUE(f.errored);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:14: unable to determine function return type");
}
TEST_F(ParserImplTest, FunctionDecl_InvalidBody) {
auto* p = parser("fn main() -> void { return }");
- auto decorations = p->decoration_list();
- ASSERT_FALSE(p->has_error()) << p->error();
- auto f = p->function_decl(decorations);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ auto f = p->function_decl(decos.value);
+ EXPECT_TRUE(f.errored);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:28: expected ';' for return statement");
}
TEST_F(ParserImplTest, FunctionDecl_MissingLeftBrace) {
auto* p = parser("fn main() -> void return; }");
- auto decorations = p->decoration_list();
- ASSERT_FALSE(p->has_error()) << p->error();
- auto f = p->function_decl(decorations);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ auto f = p->function_decl(decos.value);
+ EXPECT_TRUE(f.errored);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:19: expected '{'");
}
diff --git a/src/reader/wgsl/parser_impl_function_decoration_list_test.cc b/src/reader/wgsl/parser_impl_function_decoration_list_test.cc
index 3010a46..3250490 100644
--- a/src/reader/wgsl/parser_impl_function_decoration_list_test.cc
+++ b/src/reader/wgsl/parser_impl_function_decoration_list_test.cc
@@ -25,11 +25,13 @@
TEST_F(ParserImplTest, FunctionDecorationList_Parses) {
auto* p = parser("[[workgroup_size(2), workgroup_size(3, 4, 5)]]");
auto decos = p->decoration_list();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(decos.size(), 2u);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 2u);
- auto deco_0 = ast::As<ast::FunctionDecoration>(std::move(decos[0]));
- auto deco_1 = ast::As<ast::FunctionDecoration>(std::move(decos[1]));
+ auto deco_0 = ast::As<ast::FunctionDecoration>(std::move(decos.value[0]));
+ auto deco_1 = ast::As<ast::FunctionDecoration>(std::move(decos.value[1]));
ASSERT_NE(deco_0, nullptr);
ASSERT_NE(deco_1, nullptr);
@@ -49,47 +51,59 @@
TEST_F(ParserImplTest, FunctionDecorationList_Empty) {
auto* p = parser("[[]]");
- ast::DecorationList decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:3: empty decoration list");
+ auto decos = p->decoration_list();
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_EQ(p->error(), "1:3: empty decoration list");
}
TEST_F(ParserImplTest, FunctionDecorationList_Invalid) {
auto* p = parser("[[invalid]]");
- ast::DecorationList decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_TRUE(decos.empty());
- ASSERT_EQ(p->error(), "1:3: expected decoration");
+ auto decos = p->decoration_list();
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_TRUE(decos.value.empty());
+ EXPECT_EQ(p->error(), "1:3: expected decoration");
}
TEST_F(ParserImplTest, FunctionDecorationList_ExtraComma) {
auto* p = parser("[[workgroup_size(2), ]]");
- ast::DecorationList decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:22: expected decoration");
+ auto decos = p->decoration_list();
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_EQ(p->error(), "1:22: expected decoration");
}
TEST_F(ParserImplTest, FunctionDecorationList_MissingComma) {
auto* p = parser("[[workgroup_size(2) workgroup_size(2)]]");
- ast::DecorationList decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:21: expected ',' for decoration list");
+ auto decos = p->decoration_list();
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_EQ(p->error(), "1:21: expected ',' for decoration list");
}
TEST_F(ParserImplTest, FunctionDecorationList_BadDecoration) {
auto* p = parser("[[workgroup_size()]]");
- ast::DecorationList decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(
+ auto decos = p->decoration_list();
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_EQ(
p->error(),
"1:18: expected signed integer literal for workgroup_size x parameter");
}
TEST_F(ParserImplTest, FunctionDecorationList_MissingRightAttr) {
auto* p = parser("[[workgroup_size(2), workgroup_size(3, 4, 5)");
- ast::DecorationList decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:45: expected ']]' for decoration list");
+ auto decos = p->decoration_list();
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_EQ(p->error(), "1:45: expected ']]' for decoration list");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_function_decoration_test.cc b/src/reader/wgsl/parser_impl_function_decoration_test.cc
index 90c9344..0518569 100644
--- a/src/reader/wgsl/parser_impl_function_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_function_decoration_test.cc
@@ -26,9 +26,11 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup) {
auto* p = parser("workgroup_size(4)");
auto deco = p->decoration();
- ASSERT_NE(deco, nullptr) << p->error();
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco));
+ auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco.value));
ASSERT_NE(func_deco, nullptr);
ASSERT_TRUE(func_deco->IsWorkgroup());
@@ -44,9 +46,11 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_2Param) {
auto* p = parser("workgroup_size(4, 5)");
auto deco = p->decoration();
- ASSERT_NE(deco, nullptr) << p->error();
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco));
+ auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco.value));
ASSERT_NE(func_deco, nullptr) << p->error();
ASSERT_TRUE(func_deco->IsWorkgroup());
@@ -62,9 +66,11 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_3Param) {
auto* p = parser("workgroup_size(4, 5, 6)");
auto deco = p->decoration();
- ASSERT_NE(deco, nullptr) << p->error();
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco));
+ auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco.value));
ASSERT_NE(func_deco, nullptr);
ASSERT_TRUE(func_deco->IsWorkgroup());
@@ -80,16 +86,20 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_TooManyValues) {
auto* p = parser("workgroup_size(1, 2, 3, 4)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:23: expected ')' for workgroup_size decoration");
}
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_X_Value) {
auto* p = parser("workgroup_size(-2, 5, 6)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:16: workgroup_size x parameter must be greater than 0");
}
@@ -97,8 +107,10 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_Y_Value) {
auto* p = parser("workgroup_size(4, 0, 6)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:19: workgroup_size y parameter must be greater than 0");
}
@@ -106,8 +118,10 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Invalid_Z_Value) {
auto* p = parser("workgroup_size(4, 5, -3)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:22: workgroup_size z parameter must be greater than 0");
}
@@ -115,24 +129,30 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingLeftParam) {
auto* p = parser("workgroup_size 4, 5, 6)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:16: expected '(' for workgroup_size decoration");
}
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingRightParam) {
auto* p = parser("workgroup_size(4, 5, 6");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:23: expected ')' for workgroup_size decoration");
}
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_MissingValues) {
auto* p = parser("workgroup_size()");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(
p->error(),
"1:16: expected signed integer literal for workgroup_size x parameter");
@@ -141,8 +161,10 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_X_Value) {
auto* p = parser("workgroup_size(, 2, 3)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(
p->error(),
"1:16: expected signed integer literal for workgroup_size x parameter");
@@ -151,16 +173,20 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Comma) {
auto* p = parser("workgroup_size(1 2, 3)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:18: expected ')' for workgroup_size decoration");
}
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Value) {
auto* p = parser("workgroup_size(1, , 3)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(
p->error(),
"1:19: expected signed integer literal for workgroup_size y parameter");
@@ -169,16 +195,20 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Comma) {
auto* p = parser("workgroup_size(1, 2 3)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:21: expected ')' for workgroup_size decoration");
}
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Value) {
auto* p = parser("workgroup_size(1, 2, )");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(
p->error(),
"1:22: expected signed integer literal for workgroup_size z parameter");
@@ -187,8 +217,10 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_X_Invalid) {
auto* p = parser("workgroup_size(nan)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(
p->error(),
"1:16: expected signed integer literal for workgroup_size x parameter");
@@ -197,8 +229,10 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Y_Invalid) {
auto* p = parser("workgroup_size(2, nan)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(
p->error(),
"1:19: expected signed integer literal for workgroup_size y parameter");
@@ -207,8 +241,10 @@
TEST_F(ParserImplTest, FunctionDecoration_Workgroup_Missing_Z_Invalid) {
auto* p = parser("workgroup_size(2, 3, nan)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(
p->error(),
"1:22: expected signed integer literal for workgroup_size z parameter");
@@ -217,9 +253,11 @@
TEST_F(ParserImplTest, FunctionDecoration_Stage) {
auto* p = parser("stage(compute)");
auto deco = p->decoration();
- ASSERT_NE(deco, nullptr) << p->error();
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco));
+ auto func_deco = ast::As<ast::FunctionDecoration>(std::move(deco.value));
ASSERT_NE(func_deco, nullptr);
ASSERT_TRUE(func_deco->IsStage());
EXPECT_EQ(func_deco->AsStage()->value(), ast::PipelineStage::kCompute);
@@ -228,32 +266,40 @@
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingValue) {
auto* p = parser("stage()");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:7: invalid value for stage decoration");
}
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingInvalid) {
auto* p = parser("stage(nan)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:7: invalid value for stage decoration");
}
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingLeftParen) {
auto* p = parser("stage compute)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:7: expected '(' for stage decoration");
}
TEST_F(ParserImplTest, FunctionDecoration_Stage_MissingRightParen) {
auto* p = parser("stage(compute");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:14: expected ')' for stage decoration");
}
diff --git a/src/reader/wgsl/parser_impl_function_header_test.cc b/src/reader/wgsl/parser_impl_function_header_test.cc
index 20a94ff..a7f000b 100644
--- a/src/reader/wgsl/parser_impl_function_header_test.cc
+++ b/src/reader/wgsl/parser_impl_function_header_test.cc
@@ -27,76 +27,94 @@
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_TRUE(f.matched);
+ EXPECT_FALSE(f.errored);
+ ASSERT_NE(f.value, nullptr);
- EXPECT_EQ(f->name(), "main");
- ASSERT_EQ(f->params().size(), 2u);
- EXPECT_EQ(f->params()[0]->name(), "a");
- EXPECT_EQ(f->params()[1]->name(), "b");
- EXPECT_TRUE(f->return_type()->IsVoid());
+ EXPECT_EQ(f.value->name(), "main");
+ ASSERT_EQ(f.value->params().size(), 2u);
+ EXPECT_EQ(f.value->params()[0]->name(), "a");
+ EXPECT_EQ(f.value->params()[1]->name(), "b");
+ EXPECT_TRUE(f.value->return_type()->IsVoid());
}
TEST_F(ParserImplTest, FunctionHeader_MissingIdent) {
auto* p = parser("fn () ->");
auto f = p->function_header();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(f.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
}
TEST_F(ParserImplTest, FunctionHeader_InvalidIdent) {
auto* p = parser("fn 133main() -> i32");
auto f = p->function_header();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(f.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
}
TEST_F(ParserImplTest, FunctionHeader_MissingParenLeft) {
auto* p = parser("fn main) -> i32");
auto f = p->function_header();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(f.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:8: expected '(' for function declaration");
}
TEST_F(ParserImplTest, FunctionHeader_InvalidParamList) {
auto* p = parser("fn main(a :i32,) -> i32");
auto f = p->function_header();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(f.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:16: expected identifier for parameter");
}
TEST_F(ParserImplTest, FunctionHeader_MissingParenRight) {
auto* p = parser("fn main( -> i32");
auto f = p->function_header();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(f.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:10: expected ')' for function declaration");
}
TEST_F(ParserImplTest, FunctionHeader_MissingArrow) {
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_FALSE(f.matched);
+ EXPECT_TRUE(f.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
+ EXPECT_EQ(p->error(), "1:11: expected '->' for function declaration");
}
TEST_F(ParserImplTest, FunctionHeader_InvalidReturnType) {
auto* p = parser("fn main() -> invalid");
auto f = p->function_header();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(f.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:14: unknown constructed type 'invalid'");
}
TEST_F(ParserImplTest, FunctionHeader_MissingReturnType) {
auto* p = parser("fn main() ->");
auto f = p->function_header();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(f, nullptr);
+ EXPECT_FALSE(f.matched);
+ EXPECT_TRUE(f.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(f.value, nullptr);
EXPECT_EQ(p->error(), "1:13: unable to determine function return type");
}
diff --git a/src/reader/wgsl/parser_impl_function_type_decl_test.cc b/src/reader/wgsl/parser_impl_function_type_decl_test.cc
index 30bc605..14bf09d 100644
--- a/src/reader/wgsl/parser_impl_function_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_function_type_decl_test.cc
@@ -31,9 +31,11 @@
auto* v = tm()->Get(std::make_unique<ast::type::VoidType>());
auto* p = parser("void");
- auto* e = p->function_type_decl();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, v);
+ auto e = p->function_type_decl();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_EQ(e.value, v);
}
TEST_F(ParserImplTest, FunctionTypeDecl_Type) {
@@ -41,16 +43,20 @@
auto* vec2 = tm()->Get(std::make_unique<ast::type::VectorType>(f32, 2));
auto* p = parser("vec2<f32>");
- auto* e = p->function_type_decl();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, vec2);
+ auto e = p->function_type_decl();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_EQ(e.value, vec2);
}
TEST_F(ParserImplTest, FunctionTypeDecl_InvalidType) {
auto* p = parser("vec2<invalid>");
- auto* e = p->function_type_decl();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ auto e = p->function_type_decl();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:6: unknown constructed type 'invalid'");
}
diff --git a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
index fd2719b..929be79 100644
--- a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
@@ -26,52 +26,62 @@
TEST_F(ParserImplTest, GlobalConstantDecl) {
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_FALSE(p->has_error()) << p->error();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_NE(e.value, nullptr);
- EXPECT_TRUE(e->is_const());
- EXPECT_EQ(e->name(), "a");
- ASSERT_NE(e->type(), nullptr);
- EXPECT_TRUE(e->type()->IsF32());
+ EXPECT_TRUE(e.value->is_const());
+ EXPECT_EQ(e.value->name(), "a");
+ ASSERT_NE(e.value->type(), nullptr);
+ EXPECT_TRUE(e.value->type()->IsF32());
- EXPECT_EQ(e->source().range.begin.line, 1u);
- EXPECT_EQ(e->source().range.begin.column, 7u);
- EXPECT_EQ(e->source().range.end.line, 1u);
- EXPECT_EQ(e->source().range.end.column, 8u);
+ EXPECT_EQ(e.value->source().range.begin.line, 1u);
+ EXPECT_EQ(e.value->source().range.begin.column, 7u);
+ EXPECT_EQ(e.value->source().range.end.line, 1u);
+ EXPECT_EQ(e.value->source().range.end.column, 8u);
- ASSERT_NE(e->constructor(), nullptr);
- EXPECT_TRUE(e->constructor()->IsConstructor());
+ ASSERT_NE(e.value->constructor(), nullptr);
+ EXPECT_TRUE(e.value->constructor()->IsConstructor());
}
TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) {
auto* p = parser("const a: f32 1.");
auto e = p->global_constant_decl();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:14: expected '=' for constant declaration");
}
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
auto* p = parser("const a: invalid = 1.");
auto e = p->global_constant_decl();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:10: unknown constructed type 'invalid'");
}
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
auto* p = parser("const a: f32 = if (a) {}");
auto e = p->global_constant_decl();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:16: unable to parse const literal");
}
TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
auto* p = parser("const a: f32 =");
auto e = p->global_constant_decl();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:15: unable to parse const literal");
}
diff --git a/src/reader/wgsl/parser_impl_global_variable_decl_test.cc b/src/reader/wgsl/parser_impl_global_variable_decl_test.cc
index 49494c1..d6dbcbd 100644
--- a/src/reader/wgsl/parser_impl_global_variable_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_variable_decl_test.cc
@@ -25,130 +25,161 @@
TEST_F(ParserImplTest, GlobalVariableDecl_WithoutConstructor) {
auto* p = parser("var<out> a : f32");
- auto decorations = p->decoration_list();
- auto e = p->global_variable_decl(decorations);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ auto e = p->global_variable_decl(decos.value);
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_NE(e.value, nullptr);
- EXPECT_EQ(e->name(), "a");
- EXPECT_TRUE(e->type()->IsF32());
- EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
+ EXPECT_EQ(e.value->name(), "a");
+ EXPECT_TRUE(e.value->type()->IsF32());
+ EXPECT_EQ(e.value->storage_class(), ast::StorageClass::kOutput);
- EXPECT_EQ(e->source().range.begin.line, 1u);
- EXPECT_EQ(e->source().range.begin.column, 10u);
- EXPECT_EQ(e->source().range.end.line, 1u);
- EXPECT_EQ(e->source().range.end.column, 11u);
+ EXPECT_EQ(e.value->source().range.begin.line, 1u);
+ EXPECT_EQ(e.value->source().range.begin.column, 10u);
+ EXPECT_EQ(e.value->source().range.end.line, 1u);
+ EXPECT_EQ(e.value->source().range.end.column, 11u);
- ASSERT_EQ(e->constructor(), nullptr);
- ASSERT_FALSE(e->IsDecorated());
+ ASSERT_EQ(e.value->constructor(), nullptr);
+ ASSERT_FALSE(e.value->IsDecorated());
}
TEST_F(ParserImplTest, GlobalVariableDecl_WithConstructor) {
auto* p = parser("var<out> a : f32 = 1.");
- auto decorations = p->decoration_list();
- auto e = p->global_variable_decl(decorations);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ auto e = p->global_variable_decl(decos.value);
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_NE(e.value, nullptr);
- EXPECT_EQ(e->name(), "a");
- EXPECT_TRUE(e->type()->IsF32());
- EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
+ EXPECT_EQ(e.value->name(), "a");
+ EXPECT_TRUE(e.value->type()->IsF32());
+ EXPECT_EQ(e.value->storage_class(), ast::StorageClass::kOutput);
- EXPECT_EQ(e->source().range.begin.line, 1u);
- EXPECT_EQ(e->source().range.begin.column, 10u);
- EXPECT_EQ(e->source().range.end.line, 1u);
- EXPECT_EQ(e->source().range.end.column, 11u);
+ EXPECT_EQ(e.value->source().range.begin.line, 1u);
+ EXPECT_EQ(e.value->source().range.begin.column, 10u);
+ EXPECT_EQ(e.value->source().range.end.line, 1u);
+ EXPECT_EQ(e.value->source().range.end.column, 11u);
- ASSERT_NE(e->constructor(), nullptr);
- ASSERT_TRUE(e->constructor()->IsConstructor());
- ASSERT_TRUE(e->constructor()->AsConstructor()->IsScalarConstructor());
+ ASSERT_NE(e.value->constructor(), nullptr);
+ ASSERT_TRUE(e.value->constructor()->IsConstructor());
+ ASSERT_TRUE(e.value->constructor()->AsConstructor()->IsScalarConstructor());
- ASSERT_FALSE(e->IsDecorated());
+ ASSERT_FALSE(e.value->IsDecorated());
}
TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) {
auto* p = parser("[[binding(2), set(1)]] var<out> a : f32");
- auto decorations = p->decoration_list();
- auto e = p->global_variable_decl(decorations);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+ auto e = p->global_variable_decl(decos.value);
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsDecorated());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsDecorated());
- EXPECT_EQ(e->name(), "a");
- ASSERT_NE(e->type(), nullptr);
- EXPECT_TRUE(e->type()->IsF32());
- EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
+ EXPECT_EQ(e.value->name(), "a");
+ ASSERT_NE(e.value->type(), nullptr);
+ EXPECT_TRUE(e.value->type()->IsF32());
+ EXPECT_EQ(e.value->storage_class(), ast::StorageClass::kOutput);
- EXPECT_EQ(e->source().range.begin.line, 1u);
- EXPECT_EQ(e->source().range.begin.column, 33u);
- EXPECT_EQ(e->source().range.end.line, 1u);
- EXPECT_EQ(e->source().range.end.column, 34u);
+ EXPECT_EQ(e.value->source().range.begin.line, 1u);
+ EXPECT_EQ(e.value->source().range.begin.column, 33u);
+ EXPECT_EQ(e.value->source().range.end.line, 1u);
+ EXPECT_EQ(e.value->source().range.end.column, 34u);
- ASSERT_EQ(e->constructor(), nullptr);
+ ASSERT_EQ(e.value->constructor(), nullptr);
- ASSERT_TRUE(e->IsDecorated());
- auto* v = e->AsDecorated();
+ ASSERT_TRUE(e.value->IsDecorated());
+ auto* v = e.value->AsDecorated();
- auto& decos = v->decorations();
- ASSERT_EQ(decos.size(), 2u);
- ASSERT_TRUE(decos[0]->IsBinding());
- ASSERT_TRUE(decos[1]->IsSet());
+ auto& decorations = v->decorations();
+ ASSERT_EQ(decorations.size(), 2u);
+ ASSERT_TRUE(decorations[0]->IsBinding());
+ ASSERT_TRUE(decorations[1]->IsSet());
}
TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration_MulitpleGroups) {
auto* p = parser("[[binding(2)]] [[set(1)]] var<out> a : f32");
- auto decorations = p->decoration_list();
- auto e = p->global_variable_decl(decorations);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+
+ auto e = p->global_variable_decl(decos.value);
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsDecorated());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsDecorated());
- EXPECT_EQ(e->name(), "a");
- ASSERT_NE(e->type(), nullptr);
- EXPECT_TRUE(e->type()->IsF32());
- EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
+ EXPECT_EQ(e.value->name(), "a");
+ ASSERT_NE(e.value->type(), nullptr);
+ EXPECT_TRUE(e.value->type()->IsF32());
+ EXPECT_EQ(e.value->storage_class(), ast::StorageClass::kOutput);
- EXPECT_EQ(e->source().range.begin.line, 1u);
- EXPECT_EQ(e->source().range.begin.column, 36u);
- EXPECT_EQ(e->source().range.end.line, 1u);
- EXPECT_EQ(e->source().range.end.column, 37u);
+ EXPECT_EQ(e.value->source().range.begin.line, 1u);
+ EXPECT_EQ(e.value->source().range.begin.column, 36u);
+ EXPECT_EQ(e.value->source().range.end.line, 1u);
+ EXPECT_EQ(e.value->source().range.end.column, 37u);
- ASSERT_EQ(e->constructor(), nullptr);
+ ASSERT_EQ(e.value->constructor(), nullptr);
- ASSERT_TRUE(e->IsDecorated());
- auto* v = e->AsDecorated();
+ ASSERT_TRUE(e.value->IsDecorated());
+ auto* v = e.value->AsDecorated();
- auto& decos = v->decorations();
- ASSERT_EQ(decos.size(), 2u);
- ASSERT_TRUE(decos[0]->IsBinding());
- ASSERT_TRUE(decos[1]->IsSet());
+ auto& decorations = v->decorations();
+ ASSERT_EQ(decorations.size(), 2u);
+ ASSERT_TRUE(decorations[0]->IsBinding());
+ ASSERT_TRUE(decorations[1]->IsSet());
}
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidDecoration) {
auto* p = parser("[[binding()]] var<out> a : f32");
- auto decorations = p->decoration_list();
- auto e = p->global_variable_decl(decorations);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ auto decos = p->decoration_list();
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+
+ auto e = p->global_variable_decl(decos.value);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
+
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:11: expected signed integer literal for binding decoration");
}
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidConstExpr) {
auto* p = parser("var<out> a : f32 = if (a) {}");
- auto decorations = p->decoration_list();
- auto e = p->global_variable_decl(decorations);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ auto e = p->global_variable_decl(decos.value);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:20: unable to parse const literal");
}
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
auto* p = parser("var<invalid> a : f32;");
- auto decorations = p->decoration_list();
- auto e = p->global_variable_decl(decorations);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ auto decos = p->decoration_list();
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ auto e = p->global_variable_decl(decos.value);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable decoration");
}
diff --git a/src/reader/wgsl/parser_impl_if_stmt_test.cc b/src/reader/wgsl/parser_impl_if_stmt_test.cc
index 50c3827..8dea243 100644
--- a/src/reader/wgsl/parser_impl_if_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_if_stmt_test.cc
@@ -26,82 +26,98 @@
TEST_F(ParserImplTest, IfStmt) {
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);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsIf());
- ASSERT_NE(e->condition(), nullptr);
- ASSERT_TRUE(e->condition()->IsBinary());
- EXPECT_EQ(e->body()->size(), 2u);
- EXPECT_EQ(e->else_statements().size(), 0u);
+ ASSERT_TRUE(e.value->IsIf());
+ ASSERT_NE(e.value->condition(), nullptr);
+ ASSERT_TRUE(e.value->condition()->IsBinary());
+ EXPECT_EQ(e.value->body()->size(), 2u);
+ EXPECT_EQ(e.value->else_statements().size(), 0u);
}
TEST_F(ParserImplTest, IfStmt_WithElse) {
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);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsIf());
- ASSERT_NE(e->condition(), nullptr);
- ASSERT_TRUE(e->condition()->IsBinary());
- EXPECT_EQ(e->body()->size(), 2u);
+ ASSERT_TRUE(e.value->IsIf());
+ ASSERT_NE(e.value->condition(), nullptr);
+ ASSERT_TRUE(e.value->condition()->IsBinary());
+ EXPECT_EQ(e.value->body()->size(), 2u);
- ASSERT_EQ(e->else_statements().size(), 2u);
- ASSERT_NE(e->else_statements()[0]->condition(), nullptr);
- ASSERT_TRUE(e->else_statements()[0]->condition()->IsIdentifier());
- EXPECT_EQ(e->else_statements()[0]->body()->size(), 1u);
+ ASSERT_EQ(e.value->else_statements().size(), 2u);
+ ASSERT_NE(e.value->else_statements()[0]->condition(), nullptr);
+ ASSERT_TRUE(e.value->else_statements()[0]->condition()->IsIdentifier());
+ EXPECT_EQ(e.value->else_statements()[0]->body()->size(), 1u);
- ASSERT_EQ(e->else_statements()[1]->condition(), nullptr);
- EXPECT_EQ(e->else_statements()[1]->body()->size(), 0u);
+ ASSERT_EQ(e.value->else_statements()[1]->condition(), nullptr);
+ EXPECT_EQ(e.value->else_statements()[1]->body()->size(), 0u);
}
TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
auto* p = parser("if (a = 3) {}");
auto e = p->if_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:7: expected ')'");
}
TEST_F(ParserImplTest, IfStmt_MissingCondition) {
auto* p = parser("if {}");
auto e = p->if_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:4: expected '('");
}
TEST_F(ParserImplTest, IfStmt_InvalidBody) {
auto* p = parser("if (a) { fn main() -> void {}}");
auto e = p->if_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:10: expected '}'");
}
TEST_F(ParserImplTest, IfStmt_MissingBody) {
auto* p = parser("if (a)");
auto e = p->if_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:7: expected '{'");
}
TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
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_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:24: expected '}'");
}
TEST_F(ParserImplTest, IfStmt_InvalidElse) {
auto* p = parser("if (a) {} else { fn main() -> a{}}");
auto e = p->if_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:18: expected '}'");
}
diff --git a/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc b/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
index e7451e7..073c2be 100644
--- a/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, InclusiveOrExpression_Parses) {
auto* p = parser("a | true");
auto e = p->inclusive_or_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kOr, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,24 +51,30 @@
TEST_F(ParserImplTest, InclusiveOrExpression_InvalidLHS) {
auto* p = parser("if (a) {} | true");
auto e = p->inclusive_or_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, InclusiveOrExpression_InvalidRHS) {
auto* p = parser("true | if (a) {}");
auto e = p->inclusive_or_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:8: unable to parse right side of | expression");
}
TEST_F(ParserImplTest, InclusiveOrExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_logical_and_expression_test.cc b/src/reader/wgsl/parser_impl_logical_and_expression_test.cc
index 03b102b..c11de2a 100644
--- a/src/reader/wgsl/parser_impl_logical_and_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_logical_and_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, LogicalAndExpression_Parses) {
auto* p = parser("a && true");
auto e = p->logical_and_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kLogicalAnd, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,24 +51,30 @@
TEST_F(ParserImplTest, LogicalAndExpression_InvalidLHS) {
auto* p = parser("if (a) {} && true");
auto e = p->logical_and_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, LogicalAndExpression_InvalidRHS) {
auto* p = parser("true && if (a) {}");
auto e = p->logical_and_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: unable to parse right side of && expression");
}
TEST_F(ParserImplTest, LogicalAndExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_logical_or_expression_test.cc b/src/reader/wgsl/parser_impl_logical_or_expression_test.cc
index 444e871..3925590 100644
--- a/src/reader/wgsl/parser_impl_logical_or_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_logical_or_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, LogicalOrExpression_Parses) {
auto* p = parser("a || true");
auto e = p->logical_or_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kLogicalOr, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,24 +51,30 @@
TEST_F(ParserImplTest, LogicalOrExpression_InvalidLHS) {
auto* p = parser("if (a) {} || true");
auto e = p->logical_or_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, LogicalOrExpression_InvalidRHS) {
auto* p = parser("true || if (a) {}");
auto e = p->logical_or_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: unable to parse right side of || expression");
}
TEST_F(ParserImplTest, LogicalOrExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_loop_stmt_test.cc b/src/reader/wgsl/parser_impl_loop_stmt_test.cc
index 41aea2f..6b4aa2f 100644
--- a/src/reader/wgsl/parser_impl_loop_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_loop_stmt_test.cc
@@ -24,76 +24,92 @@
TEST_F(ParserImplTest, LoopStmt_BodyNoContinuing) {
auto* p = parser("loop { discard; }");
auto e = p->loop_stmt();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_EQ(e->body()->size(), 1u);
- EXPECT_TRUE(e->body()->get(0)->IsDiscard());
+ ASSERT_EQ(e.value->body()->size(), 1u);
+ EXPECT_TRUE(e.value->body()->get(0)->IsDiscard());
- EXPECT_EQ(e->continuing()->size(), 0u);
+ EXPECT_EQ(e.value->continuing()->size(), 0u);
}
TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
auto* p = parser("loop { discard; continuing { discard; }}");
auto e = p->loop_stmt();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_EQ(e->body()->size(), 1u);
- EXPECT_TRUE(e->body()->get(0)->IsDiscard());
+ ASSERT_EQ(e.value->body()->size(), 1u);
+ EXPECT_TRUE(e.value->body()->get(0)->IsDiscard());
- EXPECT_EQ(e->continuing()->size(), 1u);
- EXPECT_TRUE(e->continuing()->get(0)->IsDiscard());
+ EXPECT_EQ(e.value->continuing()->size(), 1u);
+ EXPECT_TRUE(e.value->continuing()->get(0)->IsDiscard());
}
TEST_F(ParserImplTest, LoopStmt_NoBodyNoContinuing) {
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(), 0u);
- ASSERT_EQ(e->continuing()->size(), 0u);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_EQ(e.value->body()->size(), 0u);
+ ASSERT_EQ(e.value->continuing()->size(), 0u);
}
TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
auto* p = parser("loop { continuing { discard; }}");
auto e = p->loop_stmt();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_EQ(e->body()->size(), 0u);
- ASSERT_EQ(e->continuing()->size(), 1u);
- EXPECT_TRUE(e->continuing()->get(0)->IsDiscard());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_EQ(e.value->body()->size(), 0u);
+ ASSERT_EQ(e.value->continuing()->size(), 1u);
+ EXPECT_TRUE(e.value->continuing()->get(0)->IsDiscard());
}
TEST_F(ParserImplTest, LoopStmt_MissingBracketLeft) {
auto* p = parser("loop discard; }");
auto e = p->loop_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:6: expected '{' for loop");
}
TEST_F(ParserImplTest, LoopStmt_MissingBracketRight) {
auto* p = parser("loop { discard; ");
auto e = p->loop_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:17: expected '}' for loop");
}
TEST_F(ParserImplTest, LoopStmt_InvalidStatements) {
auto* p = parser("loop { discard }");
auto e = p->loop_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:16: expected ';' for discard statement");
}
TEST_F(ParserImplTest, LoopStmt_InvalidContinuing) {
auto* p = parser("loop { continuing { discard }}");
auto e = p->loop_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:29: expected ';' for discard statement");
}
diff --git a/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc b/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc
index 3c6c1fa..d311020 100644
--- a/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply) {
auto* p = parser("a * true");
auto e = p->multiplicative_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,11 +51,13 @@
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
auto* p = parser("a / true");
auto e = p->multiplicative_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kDivide, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -70,11 +74,13 @@
TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
auto* p = parser("a % true");
auto e = p->multiplicative_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kModulo, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -91,24 +97,30 @@
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) {
auto* p = parser("if (a) {} * true");
auto e = p->multiplicative_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, MultiplicativeExpression_InvalidRHS) {
auto* p = parser("true * if (a) {}");
auto e = p->multiplicative_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:8: unable to parse right side of * expression");
}
TEST_F(ParserImplTest, MultiplicativeExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_postfix_expression_test.cc b/src/reader/wgsl/parser_impl_postfix_expression_test.cc
index 31ca9c6..952103b 100644
--- a/src/reader/wgsl/parser_impl_postfix_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_postfix_expression_test.cc
@@ -31,11 +31,13 @@
TEST_F(ParserImplTest, PostfixExpression_Array_ConstantIndex) {
auto* p = parser("a[1]");
auto e = p->postfix_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsArrayAccessor());
- auto* ary = e->AsArrayAccessor();
+ ASSERT_TRUE(e.value->IsArrayAccessor());
+ auto* ary = e.value->AsArrayAccessor();
ASSERT_TRUE(ary->array()->IsIdentifier());
auto* ident = ary->array()->AsIdentifier();
@@ -51,11 +53,13 @@
TEST_F(ParserImplTest, PostfixExpression_Array_ExpressionIndex) {
auto* p = parser("a[1 + b / 4]");
auto e = p->postfix_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsArrayAccessor());
- auto* ary = e->AsArrayAccessor();
+ ASSERT_TRUE(e.value->IsArrayAccessor());
+ auto* ary = e.value->AsArrayAccessor();
ASSERT_TRUE(ary->array()->IsIdentifier());
auto* ident = ary->array()->AsIdentifier();
@@ -67,35 +71,43 @@
TEST_F(ParserImplTest, PostfixExpression_Array_MissingIndex) {
auto* p = parser("a[]");
auto e = p->postfix_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
}
TEST_F(ParserImplTest, PostfixExpression_Array_MissingRightBrace) {
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_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(p->error(), "1:4: expected ']' for array accessor");
}
TEST_F(ParserImplTest, PostfixExpression_Array_InvalidIndex) {
auto* p = parser("a[if(a() {})]");
auto e = p->postfix_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
}
TEST_F(ParserImplTest, PostfixExpression_Call_Empty) {
auto* p = parser("a()");
auto e = p->postfix_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsCall());
- auto* c = e->AsCall();
+ ASSERT_TRUE(e.value->IsCall());
+ auto* c = e.value->AsCall();
ASSERT_TRUE(c->func()->IsIdentifier());
auto* func = c->func()->AsIdentifier();
@@ -107,11 +119,13 @@
TEST_F(ParserImplTest, PostfixExpression_Call_WithArgs) {
auto* p = parser("test(1, b, 2 + 3 / b)");
auto e = p->postfix_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsCall());
- auto* c = e->AsCall();
+ ASSERT_TRUE(e.value->IsCall());
+ auto* c = e.value->AsCall();
ASSERT_TRUE(c->func()->IsIdentifier());
auto* func = c->func()->AsIdentifier();
@@ -126,35 +140,43 @@
TEST_F(ParserImplTest, PostfixExpression_Call_InvalidArg) {
auto* p = parser("a(if(a) {})");
auto e = p->postfix_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:3: unable to parse argument expression");
}
TEST_F(ParserImplTest, PostfixExpression_Call_HangingComma) {
auto* p = parser("a(b, )");
auto e = p->postfix_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:6: unable to parse argument expression after comma");
}
TEST_F(ParserImplTest, PostfixExpression_Call_MissingRightParen) {
auto* p = parser("a(");
auto e = p->postfix_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:3: expected ')' for call expression");
}
TEST_F(ParserImplTest, PostfixExpression_MemberAccessor) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsMemberAccessor());
- auto* m = e->AsMemberAccessor();
+ auto* m = e.value->AsMemberAccessor();
ASSERT_TRUE(m->structure()->IsIdentifier());
EXPECT_EQ(m->structure()->AsIdentifier()->name(), "a");
@@ -165,25 +187,31 @@
TEST_F(ParserImplTest, PostfixExpression_MemberAccesssor_InvalidIdent) {
auto* p = parser("a.if");
auto e = p->postfix_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:3: expected identifier for member accessor");
}
TEST_F(ParserImplTest, PostfixExpression_MemberAccessor_MissingIdent) {
auto* p = parser("a.");
auto e = p->postfix_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:3: expected identifier for member accessor");
}
TEST_F(ParserImplTest, PostfixExpression_NonMatch_returnLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_primary_expression_test.cc b/src/reader/wgsl/parser_impl_primary_expression_test.cc
index 41c218c..3ef055d 100644
--- a/src/reader/wgsl/parser_impl_primary_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_primary_expression_test.cc
@@ -35,21 +35,25 @@
TEST_F(ParserImplTest, PrimaryExpression_Ident) {
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();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
+ auto* ident = e.value->AsIdentifier();
EXPECT_EQ(ident->name(), "a");
}
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
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->IsConstructor());
- ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
- auto* ty = e->AsConstructor()->AsTypeConstructor();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsConstructor());
+ ASSERT_TRUE(e.value->AsConstructor()->IsTypeConstructor());
+ auto* ty = e.value->AsConstructor()->AsTypeConstructor();
ASSERT_EQ(ty->values().size(), 4u);
const auto& val = ty->values();
@@ -81,11 +85,13 @@
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
auto* p = parser("vec4<i32>()");
auto e = p->primary_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsConstructor());
- ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
- auto* ty = e->AsConstructor()->AsTypeConstructor();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsConstructor());
+ ASSERT_TRUE(e.value->AsConstructor()->IsTypeConstructor());
+ auto* ty = e.value->AsConstructor()->AsTypeConstructor();
ASSERT_EQ(ty->values().size(), 0u);
}
@@ -93,43 +99,53 @@
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
auto* p = parser("vec4<if>(2., 3., 4., 5.)");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:6: unable to determine subtype for vector");
}
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_MissingLeftParen) {
auto* p = parser("vec4<f32> 2., 3., 4., 5.)");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:11: expected '(' for type constructor");
}
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_MissingRightParen) {
auto* p = parser("vec4<f32>(2., 3., 4., 5.");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:25: expected ')' for type constructor");
}
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidValue) {
auto* p = parser("i32(if(a) {})");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:5: unable to parse argument expression");
}
TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
auto* p = parser("true");
auto e = p->primary_expression();
- ASSERT_FALSE(p->has_error());
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsConstructor());
- ASSERT_TRUE(e->AsConstructor()->IsScalarConstructor());
- auto* init = e->AsConstructor()->AsScalarConstructor();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsConstructor());
+ ASSERT_TRUE(e.value->AsConstructor()->IsScalarConstructor());
+ auto* init = e.value->AsConstructor()->AsScalarConstructor();
ASSERT_TRUE(init->literal()->IsBool());
EXPECT_TRUE(init->literal()->AsBool()->IsTrue());
}
@@ -137,32 +153,40 @@
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr) {
auto* p = parser("(a == b)");
auto e = p->primary_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsBinary());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsBinary());
}
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_MissingRightParen) {
auto* p = parser("(a == b");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:8: expected ')'");
}
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_MissingExpr) {
auto* p = parser("()");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
}
TEST_F(ParserImplTest, PrimaryExpression_ParenExpr_InvalidExpr) {
auto* p = parser("(if (a) {})");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:2: unable to parse expression");
}
@@ -171,12 +195,14 @@
auto* p = parser("f32(1)");
auto e = p->primary_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsConstructor());
- ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsConstructor());
+ ASSERT_TRUE(e.value->AsConstructor()->IsTypeConstructor());
- auto* c = e->AsConstructor()->AsTypeConstructor();
+ auto* c = e.value->AsConstructor()->AsTypeConstructor();
ASSERT_EQ(c->type(), f32_type);
ASSERT_EQ(c->values().size(), 1u);
@@ -189,11 +215,13 @@
auto* p = parser("bitcast<f32>(1)");
auto e = p->primary_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsBitcast());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsBitcast());
- auto* c = e->AsBitcast();
+ auto* c = e.value->AsBitcast();
ASSERT_EQ(c->type(), f32_type);
ASSERT_TRUE(c->expr()->IsConstructor());
@@ -203,56 +231,70 @@
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingGreaterThan) {
auto* p = parser("bitcast<f32(1)");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:12: missing > for bitcast expression");
+ EXPECT_EQ(p->error(), "1:12: expected '>' for bitcast expression");
}
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingType) {
auto* p = parser("bitcast<>(1)");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:9: missing type for bitcast expression");
}
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_InvalidType) {
auto* p = parser("bitcast<invalid>(1)");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:9: unknown constructed type 'invalid'");
}
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingLeftParen) {
auto* p = parser("bitcast<f32>1)");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:13: expected '('");
}
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingRightParen) {
auto* p = parser("bitcast<f32>(1");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:15: expected ')'");
}
TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingExpression) {
auto* p = parser("bitcast<f32>()");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:14: unable to parse expression");
}
TEST_F(ParserImplTest, PrimaryExpression_bitcast_InvalidExpression) {
auto* p = parser("bitcast<f32>(if (a) {})");
auto e = p->primary_expression();
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
EXPECT_EQ(p->error(), "1:14: unable to parse expression");
}
diff --git a/src/reader/wgsl/parser_impl_relational_expression_test.cc b/src/reader/wgsl/parser_impl_relational_expression_test.cc
index 982f496..be712b9 100644
--- a/src/reader/wgsl/parser_impl_relational_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_relational_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThan) {
auto* p = parser("a < true");
auto e = p->relational_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kLessThan, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,11 +51,13 @@
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
auto* p = parser("a > true");
auto e = p->relational_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kGreaterThan, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -70,11 +74,13 @@
TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
auto* p = parser("a <= true");
auto e = p->relational_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kLessThanEqual, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -91,11 +97,13 @@
TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
auto* p = parser("a >= true");
auto e = p->relational_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kGreaterThanEqual, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -112,24 +120,28 @@
TEST_F(ParserImplTest, RelationalExpression_InvalidLHS) {
auto* p = parser("if (a) {} < true");
auto e = p->relational_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, RelationalExpression_InvalidRHS) {
auto* p = parser("true < if (a) {}");
auto e = p->relational_expression();
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:8: unable to parse right side of < expression");
}
TEST_F(ParserImplTest, RelationalExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc b/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc
index c0d6895..9406bdc 100644
--- a/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc
+++ b/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc
@@ -25,105 +25,134 @@
TEST_F(ParserImplTest, SampledTextureType_Invalid) {
auto* p = parser("1234");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::kNone);
+ EXPECT_FALSE(t.matched);
+ EXPECT_FALSE(t.errored);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_1d_Old) {
auto* p = parser("texture_sampled_1d");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k1d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k1d);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_1dArray_Old) {
auto* p = parser("texture_sampled_1d_array");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k1dArray);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k1dArray);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_2d_Old) {
auto* p = parser("texture_sampled_2d");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k2d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k2d);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_2dArray_Old) {
auto* p = parser("texture_sampled_2d_array");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k2dArray);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k2dArray);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_3d_Old) {
auto* p = parser("texture_sampled_3d");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k3d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k3d);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_Cube_Old) {
auto* p = parser("texture_sampled_cube");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::kCube);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::kCube);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_kCubeArray_Old) {
auto* p = parser("texture_sampled_cube_array");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::kCubeArray);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::kCubeArray);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_1d) {
auto* p = parser("texture_1d");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k1d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k1d);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_1dArray) {
auto* p = parser("texture_1d_array");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k1dArray);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k1dArray);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_2d) {
auto* p = parser("texture_2d");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k2d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k2d);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_2dArray) {
auto* p = parser("texture_2d_array");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k2dArray);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k2dArray);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_3d) {
auto* p = parser("texture_3d");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::k3d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::k3d);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_Cube) {
auto* p = parser("texture_cube");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::kCube);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::kCube);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SampledTextureType_kCubeArray) {
auto* p = parser("texture_cube_array");
auto t = p->sampled_texture_type();
- EXPECT_EQ(t, ast::type::TextureDimension::kCubeArray);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, ast::type::TextureDimension::kCubeArray);
EXPECT_FALSE(p->has_error());
}
diff --git a/src/reader/wgsl/parser_impl_sampler_type_test.cc b/src/reader/wgsl/parser_impl_sampler_type_test.cc
index db71a20..caf313c 100644
--- a/src/reader/wgsl/parser_impl_sampler_type_test.cc
+++ b/src/reader/wgsl/parser_impl_sampler_type_test.cc
@@ -24,26 +24,32 @@
TEST_F(ParserImplTest, SamplerType_Invalid) {
auto* p = parser("1234");
- auto* t = p->sampler_type();
- EXPECT_EQ(t, nullptr);
+ auto t = p->sampler_type();
+ EXPECT_FALSE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(t.value, nullptr);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SamplerType_Sampler) {
auto* p = parser("sampler");
- auto* t = p->sampler_type();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsSampler());
- EXPECT_FALSE(t->AsSampler()->IsComparison());
+ auto t = p->sampler_type();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsSampler());
+ EXPECT_FALSE(t.value->AsSampler()->IsComparison());
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, SamplerType_ComparisonSampler) {
auto* p = parser("sampler_comparison");
- auto* t = p->sampler_type();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsSampler());
- EXPECT_TRUE(t->AsSampler()->IsComparison());
+ auto t = p->sampler_type();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsSampler());
+ EXPECT_TRUE(t.value->AsSampler()->IsComparison());
EXPECT_FALSE(p->has_error());
}
diff --git a/src/reader/wgsl/parser_impl_shift_expression_test.cc b/src/reader/wgsl/parser_impl_shift_expression_test.cc
index 2acf06b..2122bfd 100644
--- a/src/reader/wgsl/parser_impl_shift_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_shift_expression_test.cc
@@ -28,11 +28,13 @@
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftLeft) {
auto* p = parser("a << true");
auto e = p->shift_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kShiftLeft, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -49,11 +51,13 @@
TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) {
auto* p = parser("a >> true");
auto e = p->shift_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsBinary());
- auto* rel = e->AsBinary();
+ ASSERT_TRUE(e.value->IsBinary());
+ auto* rel = e.value->AsBinary();
EXPECT_EQ(ast::BinaryOp::kShiftRight, rel->op());
ASSERT_TRUE(rel->lhs()->IsIdentifier());
@@ -70,24 +74,30 @@
TEST_F(ParserImplTest, ShiftExpression_InvalidLHS) {
auto* p = parser("if (a) {} << true");
auto e = p->shift_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_EQ(e.value, nullptr);
}
TEST_F(ParserImplTest, ShiftExpression_InvalidRHS) {
auto* p = parser("true << if (a) {}");
auto e = p->shift_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:9: unable to parse right side of << expression");
}
TEST_F(ParserImplTest, ShiftExpression_NoOr_ReturnsLHS) {
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());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsIdentifier());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_statement_test.cc b/src/reader/wgsl/parser_impl_statement_test.cc
index 2cebedf..57c5cb1 100644
--- a/src/reader/wgsl/parser_impl_statement_test.cc
+++ b/src/reader/wgsl/parser_impl_statement_test.cc
@@ -27,25 +27,25 @@
auto* p = parser("return;");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- EXPECT_TRUE(e->IsReturn());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsReturn());
}
TEST_F(ParserImplTest, Statement_Semicolon) {
auto* p = parser(";");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(e, nullptr);
}
TEST_F(ParserImplTest, Statement_Return_NoValue) {
auto* p = parser("return;");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
-
- ASSERT_TRUE(e->IsReturn());
- auto* ret = e->AsReturn();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsReturn());
+ auto* ret = e.value->AsReturn();
ASSERT_EQ(ret->value(), nullptr);
}
@@ -53,10 +53,11 @@
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());
- auto* ret = e->AsReturn();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsReturn());
+ auto* ret = e.value->AsReturn();
ASSERT_NE(ret->value(), nullptr);
EXPECT_TRUE(ret->value()->IsBinary());
}
@@ -64,16 +65,20 @@
TEST_F(ParserImplTest, Statement_Return_MissingSemi) {
auto* p = parser("return");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:7: expected ';' for return statement");
}
TEST_F(ParserImplTest, Statement_Return_Invalid) {
auto* p = parser("return if(a) {};");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:8: expected ';' for return statement");
}
@@ -81,15 +86,18 @@
auto* p = parser("if (a) {}");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsIf());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsIf());
}
TEST_F(ParserImplTest, Statement_If_Invalid) {
auto* p = parser("if (a) { fn main() -> {}}");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:10: expected '}'");
}
@@ -97,23 +105,28 @@
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->IsVariableDecl());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsVariableDecl());
}
TEST_F(ParserImplTest, Statement_Variable_Invalid) {
auto* p = parser("var a : i32 =;");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:14: missing constructor for variable declaration");
}
TEST_F(ParserImplTest, Statement_Variable_MissingSemicolon) {
auto* p = parser("var a : i32");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:12: expected ';' for variable declaration");
}
@@ -121,15 +134,18 @@
auto* p = parser("switch (a) {}");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsSwitch());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsSwitch());
}
TEST_F(ParserImplTest, Statement_Switch_Invalid) {
auto* p = parser("switch (a) { case: {}}");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:18: unable to parse case selectors");
}
@@ -137,15 +153,18 @@
auto* p = parser("loop {}");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsLoop());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsLoop());
}
TEST_F(ParserImplTest, Statement_Loop_Invalid) {
auto* p = parser("loop discard; }");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:6: expected '{' for loop");
}
@@ -153,23 +172,28 @@
auto* p = parser("a = b;");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- EXPECT_TRUE(e->IsAssign());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsAssign());
}
TEST_F(ParserImplTest, Statement_Assignment_Invalid) {
auto* p = parser("a = if(b) {};");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:5: unable to parse right side of assignment");
}
TEST_F(ParserImplTest, Statement_Assignment_MissingSemicolon) {
auto* p = parser("a = b");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:6: expected ';' for assignment statement");
}
@@ -177,15 +201,18 @@
auto* p = parser("break;");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- EXPECT_TRUE(e->IsBreak());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsBreak());
}
TEST_F(ParserImplTest, Statement_Break_MissingSemicolon) {
auto* p = parser("break");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:6: expected ';' for break statement");
}
@@ -193,15 +220,18 @@
auto* p = parser("continue;");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- EXPECT_TRUE(e->IsContinue());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsContinue());
}
TEST_F(ParserImplTest, Statement_Continue_MissingSemicolon) {
auto* p = parser("continue");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:9: expected ';' for continue statement");
}
@@ -209,15 +239,19 @@
auto* p = parser("discard;");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- EXPECT_NE(e, nullptr);
- ASSERT_TRUE(e->IsDiscard());
+ ASSERT_NE(e.value, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsDiscard());
}
TEST_F(ParserImplTest, Statement_Discard_MissingSemicolon) {
auto* p = parser("discard");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- EXPECT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
EXPECT_EQ(p->error(), "1:8: expected ';' for discard statement");
}
@@ -225,16 +259,19 @@
auto* p = parser("{ var i: i32; }");
auto e = p->statement();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsBlock());
- EXPECT_TRUE(e->AsBlock()->get(0)->IsVariableDecl());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_TRUE(e.value->IsBlock());
+ EXPECT_TRUE(e.value->AsBlock()->get(0)->IsVariableDecl());
}
TEST_F(ParserImplTest, Statement_Body_Invalid) {
auto* p = parser("{ fn main() -> {}}");
auto e = p->statement();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:3: expected '}'");
}
diff --git a/src/reader/wgsl/parser_impl_storage_texture_type_test.cc b/src/reader/wgsl/parser_impl_storage_texture_type_test.cc
index fd9ba94..2f6df88 100644
--- a/src/reader/wgsl/parser_impl_storage_texture_type_test.cc
+++ b/src/reader/wgsl/parser_impl_storage_texture_type_test.cc
@@ -25,168 +25,208 @@
TEST_F(ParserImplTest, StorageTextureType_Invalid) {
auto* p = parser("abc");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::kNone);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_FALSE(t.matched);
+ EXPECT_FALSE(t.errored);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Readonly1d_Old) {
auto* p = parser("texture_ro_1d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Readonly1dArray_Old) {
auto* p = parser("texture_ro_1d_array");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1dArray);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1dArray);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Readonly2d_Old) {
auto* p = parser("texture_ro_2d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Readonly2dArray_Old) {
auto* p = parser("texture_ro_2d_array");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2dArray);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2dArray);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Readonly3d_Old) {
auto* p = parser("texture_ro_3d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k3d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k3d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Writeonly1d_Old) {
auto* p = parser("texture_wo_1d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Writeonly1dArray_Old) {
auto* p = parser("texture_wo_1d_array");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1dArray);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1dArray);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Writeonly2d_Old) {
auto* p = parser("texture_wo_2d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Writeonly2dArray_Old) {
auto* p = parser("texture_wo_2d_array");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2dArray);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2dArray);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_Writeonly3d_Old) {
auto* p = parser("texture_wo_3d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k3d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k3d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_ro_1d) {
auto* p = parser("texture_storage_ro_1d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_ro_1dArray) {
auto* p = parser("texture_storage_ro_1d_array");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1dArray);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1dArray);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_ro_2d) {
auto* p = parser("texture_storage_ro_2d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_ro_2dArray) {
auto* p = parser("texture_storage_ro_2d_array");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2dArray);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2dArray);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_ro_3d) {
auto* p = parser("texture_storage_ro_3d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k3d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kReadOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k3d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kReadOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_wo_1d) {
auto* p = parser("texture_storage_wo_1d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_wo_1dArray) {
auto* p = parser("texture_storage_wo_1d_array");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k1dArray);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k1dArray);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_wo_2d) {
auto* p = parser("texture_storage_wo_2d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_wo_2dArray) {
auto* p = parser("texture_storage_wo_2d_array");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k2dArray);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k2dArray);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, StorageTextureType_wo_3d) {
auto* p = parser("texture_storage_wo_3d");
auto t = p->storage_texture_type();
- EXPECT_EQ(std::get<0>(t), ast::type::TextureDimension::k3d);
- EXPECT_EQ(std::get<1>(t), ast::AccessControl::kWriteOnly);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ EXPECT_EQ(std::get<0>(t.value), ast::type::TextureDimension::k3d);
+ EXPECT_EQ(std::get<1>(t.value), ast::AccessControl::kWriteOnly);
EXPECT_FALSE(p->has_error());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_struct_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decl_test.cc
index 78aafaa..81fac22 100644
--- a/src/reader/wgsl/parser_impl_struct_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decl_test.cc
@@ -29,14 +29,19 @@
[[offset(4)]] b : f32;
})");
auto decos = p->decoration_list();
- ASSERT_EQ(decos.size(), 0u);
- auto s = p->struct_decl(decos);
- ASSERT_FALSE(p->has_error());
- ASSERT_NE(s, nullptr);
- ASSERT_EQ(s->name(), "S");
- ASSERT_EQ(s->impl()->members().size(), 2u);
- EXPECT_EQ(s->impl()->members()[0]->name(), "a");
- EXPECT_EQ(s->impl()->members()[1]->name(), "b");
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 0u);
+
+ auto s = p->struct_decl(decos.value);
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(s.errored);
+ EXPECT_TRUE(s.matched);
+ ASSERT_NE(s.value, nullptr);
+ ASSERT_EQ(s.value->name(), "S");
+ ASSERT_EQ(s.value->impl()->members().size(), 2u);
+ EXPECT_EQ(s.value->impl()->members()[0]->name(), "a");
+ EXPECT_EQ(s.value->impl()->members()[1]->name(), "b");
}
TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
@@ -46,16 +51,21 @@
b : f32;
})");
auto decos = p->decoration_list();
- ASSERT_EQ(decos.size(), 1u);
- auto s = p->struct_decl(decos);
- ASSERT_FALSE(p->has_error());
- ASSERT_NE(s, nullptr);
- ASSERT_EQ(s->name(), "B");
- ASSERT_EQ(s->impl()->members().size(), 2u);
- EXPECT_EQ(s->impl()->members()[0]->name(), "a");
- EXPECT_EQ(s->impl()->members()[1]->name(), "b");
- ASSERT_EQ(s->impl()->decorations().size(), 1u);
- EXPECT_TRUE(s->impl()->decorations()[0]->IsBlock());
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 1u);
+
+ auto s = p->struct_decl(decos.value);
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(s.errored);
+ EXPECT_TRUE(s.matched);
+ ASSERT_NE(s.value, nullptr);
+ ASSERT_EQ(s.value->name(), "B");
+ ASSERT_EQ(s.value->impl()->members().size(), 2u);
+ EXPECT_EQ(s.value->impl()->members()[0]->name(), "a");
+ EXPECT_EQ(s.value->impl()->members()[1]->name(), "b");
+ ASSERT_EQ(s.value->impl()->decorations().size(), 1u);
+ EXPECT_TRUE(s.value->impl()->decorations()[0]->IsBlock());
}
TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) {
@@ -66,75 +76,115 @@
b : f32;
})");
auto decos = p->decoration_list();
- ASSERT_EQ(decos.size(), 2u);
- auto s = p->struct_decl(decos);
- ASSERT_FALSE(p->has_error());
- ASSERT_NE(s, nullptr);
- ASSERT_EQ(s->name(), "S");
- ASSERT_EQ(s->impl()->members().size(), 2u);
- EXPECT_EQ(s->impl()->members()[0]->name(), "a");
- EXPECT_EQ(s->impl()->members()[1]->name(), "b");
- ASSERT_EQ(s->impl()->decorations().size(), 2u);
- EXPECT_TRUE(s->impl()->decorations()[0]->IsBlock());
- EXPECT_TRUE(s->impl()->decorations()[1]->IsBlock());
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 2u);
+
+ auto s = p->struct_decl(decos.value);
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(s.errored);
+ EXPECT_TRUE(s.matched);
+ ASSERT_NE(s.value, nullptr);
+ ASSERT_EQ(s.value->name(), "S");
+ ASSERT_EQ(s.value->impl()->members().size(), 2u);
+ EXPECT_EQ(s.value->impl()->members()[0]->name(), "a");
+ EXPECT_EQ(s.value->impl()->members()[1]->name(), "b");
+ ASSERT_EQ(s.value->impl()->decorations().size(), 2u);
+ EXPECT_TRUE(s.value->impl()->decorations()[0]->IsBlock());
+ EXPECT_TRUE(s.value->impl()->decorations()[1]->IsBlock());
}
TEST_F(ParserImplTest, StructDecl_EmptyMembers) {
auto* p = parser("struct S {}");
auto decos = p->decoration_list();
- ASSERT_EQ(decos.size(), 0u);
- auto s = p->struct_decl(decos);
- ASSERT_FALSE(p->has_error());
- ASSERT_NE(s, nullptr);
- ASSERT_EQ(s->impl()->members().size(), 0u);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 0u);
+
+ auto s = p->struct_decl(decos.value);
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(s.errored);
+ EXPECT_TRUE(s.matched);
+ ASSERT_NE(s.value, nullptr);
+ ASSERT_EQ(s.value->impl()->members().size(), 0u);
}
TEST_F(ParserImplTest, StructDecl_MissingIdent) {
auto* p = parser("struct {}");
auto decos = p->decoration_list();
- ASSERT_EQ(decos.size(), 0u);
- auto s = p->struct_decl(decos);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(s, nullptr);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 0u);
+
+ auto s = p->struct_decl(decos.value);
+ EXPECT_TRUE(s.errored);
+ EXPECT_FALSE(s.matched);
+ EXPECT_EQ(s.value, nullptr);
+
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:8: expected identifier for struct declaration");
}
TEST_F(ParserImplTest, StructDecl_MissingBracketLeft) {
auto* p = parser("struct S }");
auto decos = p->decoration_list();
- ASSERT_EQ(decos.size(), 0u);
- auto s = p->struct_decl(decos);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(s, nullptr);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 0u);
+
+ auto s = p->struct_decl(decos.value);
+ EXPECT_TRUE(s.errored);
+ EXPECT_FALSE(s.matched);
+ EXPECT_EQ(s.value, nullptr);
+
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:10: expected '{' for struct declaration");
}
TEST_F(ParserImplTest, StructDecl_InvalidStructBody) {
auto* p = parser("struct S { a : B; }");
auto decos = p->decoration_list();
- ASSERT_EQ(decos.size(), 0u);
- auto s = p->struct_decl(decos);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(s, nullptr);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 0u);
+
+ auto s = p->struct_decl(decos.value);
+ EXPECT_TRUE(s.errored);
+ EXPECT_FALSE(s.matched);
+ EXPECT_EQ(s.value, nullptr);
+
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:16: unknown constructed type 'B'");
}
TEST_F(ParserImplTest, StructDecl_InvalidStructDecorationDecl) {
auto* p = parser("[[block struct S { a : i32; }");
auto decos = p->decoration_list();
- auto s = p->struct_decl(decos);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(s, nullptr);
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+
+ auto s = p->struct_decl(decos.value);
+ EXPECT_FALSE(s.errored);
+ EXPECT_FALSE(s.matched);
+ EXPECT_EQ(s.value, nullptr);
+
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: expected ']]' for decoration list");
}
TEST_F(ParserImplTest, StructDecl_MissingStruct) {
auto* p = parser("[[block]] S {}");
auto decos = p->decoration_list();
- ASSERT_EQ(decos.size(), 1u);
- auto s = p->struct_decl(decos);
- ASSERT_FALSE(p->has_error());
- ASSERT_EQ(s, nullptr);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 1u);
+
+ auto s = p->struct_decl(decos.value);
+ EXPECT_FALSE(s.errored);
+ EXPECT_FALSE(s.matched);
+ EXPECT_EQ(s.value, nullptr);
+
+ EXPECT_FALSE(p->has_error());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
index 0549a29..f33356d 100644
--- a/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
@@ -24,25 +24,31 @@
TEST_F(ParserImplTest, StructDecorationDecl_Parses) {
auto* p = parser("[[block]]");
auto decos = p->decoration_list();
- ASSERT_FALSE(p->has_error());
- ASSERT_EQ(decos.size(), 1u);
- auto struct_deco = ast::As<ast::StructDecoration>(std::move(decos[0]));
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 1u);
+ auto struct_deco = ast::As<ast::StructDecoration>(std::move(decos.value[0]));
EXPECT_TRUE(struct_deco->IsBlock());
}
TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {
auto* p = parser("[[block");
auto decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_TRUE(decos.value.empty());
EXPECT_EQ(p->error(), "1:8: expected ']]' for decoration list");
}
TEST_F(ParserImplTest, StructDecorationDecl_InvalidDecoration) {
auto* p = parser("[[invalid]]");
auto decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- EXPECT_EQ(decos.size(), 0u);
- EXPECT_TRUE(decos.empty());
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_TRUE(decos.value.empty());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_struct_decoration_test.cc b/src/reader/wgsl/parser_impl_struct_decoration_test.cc
index 84c6e22..f04658e 100644
--- a/src/reader/wgsl/parser_impl_struct_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decoration_test.cc
@@ -40,8 +40,10 @@
auto deco = p->decoration();
ASSERT_FALSE(p->has_error());
- ASSERT_NE(deco, nullptr);
- auto struct_deco = ast::As<ast::StructDecoration>(std::move(deco));
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr);
+ auto struct_deco = ast::As<ast::StructDecoration>(std::move(deco.value));
ASSERT_NE(struct_deco, nullptr);
EXPECT_EQ(struct_deco->IsBlock(), params.is_block);
}
@@ -52,7 +54,9 @@
TEST_F(ParserImplTest, StructDecoration_NoMatch) {
auto* p = parser("not-a-stage");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
+ EXPECT_FALSE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_EQ(deco.value, nullptr);
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_struct_member_decoration_decl_test.cc b/src/reader/wgsl/parser_impl_struct_member_decoration_decl_test.cc
index 36cc93d..df92f11 100644
--- a/src/reader/wgsl/parser_impl_struct_member_decoration_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_member_decoration_decl_test.cc
@@ -25,40 +25,50 @@
TEST_F(ParserImplTest, StructMemberDecorationDecl_EmptyStr) {
auto* p = parser("");
auto decos = p->decoration_list();
- ASSERT_FALSE(p->has_error());
- EXPECT_EQ(decos.size(), 0u);
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_EQ(decos.value.size(), 0u);
}
TEST_F(ParserImplTest, StructMemberDecorationDecl_EmptyBlock) {
auto* p = parser("[[]]");
auto decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- EXPECT_EQ(decos.size(), 0u);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_EQ(decos.value.size(), 0u);
EXPECT_EQ(p->error(), "1:3: empty decoration list");
}
TEST_F(ParserImplTest, StructMemberDecorationDecl_Single) {
auto* p = parser("[[offset(4)]]");
auto decos = p->decoration_list();
- ASSERT_FALSE(p->has_error());
- ASSERT_EQ(decos.size(), 1u);
- auto deco = ast::As<ast::StructMemberDecoration>(std::move(decos[0]));
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 1u);
+ auto deco = ast::As<ast::StructMemberDecoration>(std::move(decos.value[0]));
ASSERT_NE(deco, nullptr);
EXPECT_TRUE(deco->IsOffset());
}
TEST_F(ParserImplTest, StructMemberDecorationDecl_InvalidDecoration) {
auto* p = parser("[[offset(nan)]]");
- p->decoration_list();
- ASSERT_TRUE(p->has_error()) << p->error();
+ auto decos = p->decoration_list();
+ EXPECT_TRUE(p->has_error()) << p->error();
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
EXPECT_EQ(p->error(),
"1:10: expected signed integer literal for offset decoration");
}
TEST_F(ParserImplTest, StructMemberDecorationDecl_MissingClose) {
auto* p = parser("[[offset(4)");
- p->decoration_list();
- ASSERT_TRUE(p->has_error()) << p->error();
+ auto decos = p->decoration_list();
+ EXPECT_TRUE(p->has_error()) << p->error();
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
EXPECT_EQ(p->error(), "1:12: expected ']]' for decoration list");
}
diff --git a/src/reader/wgsl/parser_impl_struct_member_decoration_test.cc b/src/reader/wgsl/parser_impl_struct_member_decoration_test.cc
index ec25733..8872c8e 100644
--- a/src/reader/wgsl/parser_impl_struct_member_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_member_decoration_test.cc
@@ -25,10 +25,13 @@
TEST_F(ParserImplTest, StructMemberDecoration_Offset) {
auto* p = parser("offset(4)");
auto deco = p->decoration();
- ASSERT_NE(deco, nullptr);
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr);
ASSERT_FALSE(p->has_error());
- auto member_deco = ast::As<ast::StructMemberDecoration>(std::move(deco));
+ auto member_deco =
+ ast::As<ast::StructMemberDecoration>(std::move(deco.value));
ASSERT_NE(member_deco, nullptr);
ASSERT_TRUE(member_deco->IsOffset());
@@ -39,24 +42,30 @@
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingLeftParen) {
auto* p = parser("offset 4)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:8: expected '(' for offset decoration");
}
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingRightParen) {
auto* p = parser("offset(4");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: expected ')' for offset decoration");
}
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingValue) {
auto* p = parser("offset()");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:8: expected signed integer literal for offset decoration");
}
@@ -64,8 +73,10 @@
TEST_F(ParserImplTest, StructMemberDecoration_Offset_MissingInvalid) {
auto* p = parser("offset(nan)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:8: expected signed integer literal for offset decoration");
}
diff --git a/src/reader/wgsl/parser_impl_struct_member_test.cc b/src/reader/wgsl/parser_impl_struct_member_test.cc
index 563ece6..b63ee50 100644
--- a/src/reader/wgsl/parser_impl_struct_member_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_member_test.cc
@@ -29,8 +29,11 @@
auto* p = parser("a : i32;");
auto decos = p->decoration_list();
- EXPECT_EQ(decos.size(), 0u);
- auto m = p->expect_struct_member(decos);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_EQ(decos.value.size(), 0u);
+
+ auto m = p->expect_struct_member(decos.value);
ASSERT_FALSE(p->has_error());
ASSERT_FALSE(m.errored);
ASSERT_NE(m.value, nullptr);
@@ -50,8 +53,11 @@
auto* p = parser("[[offset(2)]] a : i32;");
auto decos = p->decoration_list();
- EXPECT_EQ(decos.size(), 1u);
- auto m = p->expect_struct_member(decos);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+ EXPECT_EQ(decos.value.size(), 1u);
+
+ auto m = p->expect_struct_member(decos.value);
ASSERT_FALSE(p->has_error());
ASSERT_FALSE(m.errored);
ASSERT_NE(m.value, nullptr);
@@ -74,8 +80,11 @@
auto* p = parser(R"([[offset(2)]]
[[offset(4)]] a : i32;)");
auto decos = p->decoration_list();
- EXPECT_EQ(decos.size(), 2u);
- auto m = p->expect_struct_member(decos);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+ EXPECT_EQ(decos.value.size(), 2u);
+
+ auto m = p->expect_struct_member(decos.value);
ASSERT_FALSE(p->has_error());
ASSERT_FALSE(m.errored);
ASSERT_NE(m.value, nullptr);
@@ -97,7 +106,10 @@
TEST_F(ParserImplTest, StructMember_InvalidDecoration) {
auto* p = parser("[[offset(nan)]] a : i32;");
auto decos = p->decoration_list();
- auto m = p->expect_struct_member(decos);
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+
+ auto m = p->expect_struct_member(decos.value);
ASSERT_TRUE(p->has_error());
ASSERT_TRUE(m.errored);
ASSERT_EQ(m.value, nullptr);
@@ -108,7 +120,10 @@
TEST_F(ParserImplTest, StructMember_InvalidVariable) {
auto* p = parser("[[offset(4)]] a : B;");
auto decos = p->decoration_list();
- auto m = p->expect_struct_member(decos);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_TRUE(decos.matched);
+
+ auto m = p->expect_struct_member(decos.value);
ASSERT_TRUE(p->has_error());
ASSERT_TRUE(m.errored);
ASSERT_EQ(m.value, nullptr);
@@ -118,7 +133,10 @@
TEST_F(ParserImplTest, StructMember_MissingSemicolon) {
auto* p = parser("a : i32");
auto decos = p->decoration_list();
- auto m = p->expect_struct_member(decos);
+ EXPECT_FALSE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+
+ auto m = p->expect_struct_member(decos.value);
ASSERT_TRUE(p->has_error());
ASSERT_TRUE(m.errored);
ASSERT_EQ(m.value, nullptr);
diff --git a/src/reader/wgsl/parser_impl_switch_body_test.cc b/src/reader/wgsl/parser_impl_switch_body_test.cc
index 6b4078c..69af79f 100644
--- a/src/reader/wgsl/parser_impl_switch_body_test.cc
+++ b/src/reader/wgsl/parser_impl_switch_body_test.cc
@@ -25,110 +25,136 @@
TEST_F(ParserImplTest, SwitchBody_Case) {
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());
- ASSERT_EQ(e->body()->size(), 1u);
- EXPECT_TRUE(e->body()->get(0)->IsAssign());
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsCase());
+ EXPECT_FALSE(e.value->IsDefault());
+ ASSERT_EQ(e.value->body()->size(), 1u);
+ EXPECT_TRUE(e.value->body()->get(0)->IsAssign());
}
TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
auto* p = parser("case a == 4: { a = 4; }");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:6: unable to parse case selectors");
}
TEST_F(ParserImplTest, SwitchBody_Case_InvalidSelector_bool) {
auto* p = parser("case true: { a = 4; }");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:6: invalid case selector must be an integer value");
}
TEST_F(ParserImplTest, SwitchBody_Case_MissingConstLiteral) {
auto* p = parser("case: { a = 4; }");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:5: unable to parse case selectors");
}
TEST_F(ParserImplTest, SwitchBody_Case_MissingColon) {
auto* p = parser("case 1 { a = 4; }");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:8: expected ':' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketLeft) {
auto* p = parser("case 1: a = 4; }");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:9: expected '{' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketRight) {
auto* p = parser("case 1: { a = 4; ");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:18: expected '}' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Case_InvalidCaseBody) {
auto* p = parser("case 1: { fn main() -> void {} }");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:11: expected '}' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Default) {
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());
- ASSERT_EQ(e->body()->size(), 1u);
- EXPECT_TRUE(e->body()->get(0)->IsAssign());
+ EXPECT_FALSE(p->has_error()) << p->error();
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsCase());
+ EXPECT_TRUE(e.value->IsDefault());
+ ASSERT_EQ(e.value->body()->size(), 1u);
+ EXPECT_TRUE(e.value->body()->get(0)->IsAssign());
}
TEST_F(ParserImplTest, SwitchBody_Default_MissingColon) {
auto* p = parser("default { a = 4; }");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:9: expected ':' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketLeft) {
auto* p = parser("default: a = 4; }");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:10: expected '{' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketRight) {
auto* p = parser("default: { a = 4; ");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:19: expected '}' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Default_InvalidCaseBody) {
auto* p = parser("default: { fn main() -> void {} }");
auto e = p->switch_body();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(e.errored);
+ EXPECT_FALSE(e.matched);
+ EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:12: expected '}' for case statement");
}
diff --git a/src/reader/wgsl/parser_impl_switch_stmt_test.cc b/src/reader/wgsl/parser_impl_switch_stmt_test.cc
index 15b6a5c..d0ea352 100644
--- a/src/reader/wgsl/parser_impl_switch_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_switch_stmt_test.cc
@@ -29,21 +29,25 @@
case 2: {}
})");
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(), 2u);
- EXPECT_FALSE(e->body()[0]->IsDefault());
- EXPECT_FALSE(e->body()[1]->IsDefault());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsSwitch());
+ ASSERT_EQ(e.value->body().size(), 2u);
+ EXPECT_FALSE(e.value->body()[0]->IsDefault());
+ EXPECT_FALSE(e.value->body()[1]->IsDefault());
}
TEST_F(ParserImplTest, SwitchStmt_Empty) {
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(), 0u);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsSwitch());
+ ASSERT_EQ(e.value->body().size(), 0u);
}
TEST_F(ParserImplTest, SwitchStmt_DefaultInMiddle) {
@@ -53,45 +57,55 @@
case 2: {}
})");
auto e = p->switch_stmt();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsSwitch());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsSwitch());
- ASSERT_EQ(e->body().size(), 3u);
- ASSERT_FALSE(e->body()[0]->IsDefault());
- ASSERT_TRUE(e->body()[1]->IsDefault());
- ASSERT_FALSE(e->body()[2]->IsDefault());
+ ASSERT_EQ(e.value->body().size(), 3u);
+ ASSERT_FALSE(e.value->body()[0]->IsDefault());
+ ASSERT_TRUE(e.value->body()[1]->IsDefault());
+ ASSERT_FALSE(e.value->body()[2]->IsDefault());
}
TEST_F(ParserImplTest, SwitchStmt_InvalidExpression) {
auto* p = parser("switch(a=b) {}");
auto e = p->switch_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: expected ')'");
}
TEST_F(ParserImplTest, SwitchStmt_MissingExpression) {
auto* p = parser("switch {}");
auto e = p->switch_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:8: expected '('");
}
TEST_F(ParserImplTest, SwitchStmt_MissingBracketLeft) {
auto* p = parser("switch(a) }");
auto e = p->switch_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:11: expected '{' for switch statement");
}
TEST_F(ParserImplTest, SwitchStmt_MissingBracketRight) {
auto* p = parser("switch(a) {");
auto e = p->switch_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:12: expected '}' for switch statement");
}
@@ -100,8 +114,10 @@
case: {}
})");
auto e = p->switch_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "2:7: unable to parse case selectors");
}
diff --git a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
index 0e82af0..b040fad 100644
--- a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
+++ b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
@@ -26,325 +26,395 @@
TEST_F(ParserImplTest, TextureSamplerTypes_Invalid) {
auto* p = parser("1234");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_FALSE(t.errored);
EXPECT_FALSE(p->has_error());
}
TEST_F(ParserImplTest, TextureSamplerTypes_Sampler) {
auto* p = parser("sampler");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsSampler());
- ASSERT_FALSE(t->AsSampler()->IsComparison());
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsSampler());
+ ASSERT_FALSE(t.value->AsSampler()->IsComparison());
}
TEST_F(ParserImplTest, TextureSamplerTypes_SamplerComparison) {
auto* p = parser("sampler_comparison");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsSampler());
- ASSERT_TRUE(t->AsSampler()->IsComparison());
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsSampler());
+ ASSERT_TRUE(t.value->AsSampler()->IsComparison());
}
TEST_F(ParserImplTest, TextureSamplerTypes_DepthTexture) {
auto* p = parser("texture_depth_2d");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsDepth());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsDepth());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_F32_Old) {
auto* p = parser("texture_sampled_1d<f32>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsSampled());
- ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsF32());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsSampled());
+ ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsF32());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k1d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_I32_Old) {
auto* p = parser("texture_sampled_2d<i32>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsSampled());
- ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsI32());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsSampled());
+ ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsI32());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_U32_Old) {
auto* p = parser("texture_sampled_3d<u32>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsSampled());
- ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsU32());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k3d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsSampled());
+ ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsU32());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k3d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_Invalid_Old) {
auto* p = parser("texture_sampled_1d<abc>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:20: unknown constructed type 'abc'");
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType_Old) {
auto* p = parser("texture_sampled_1d<>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:20: invalid subtype for sampled texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan_Old) {
auto* p = parser("texture_sampled_1d");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:19: expected '<' for sampled texture type");
}
TEST_F(ParserImplTest,
TextureSamplerTypes_SampledTexture_MissingGreaterThan_Old) {
auto* p = parser("texture_sampled_1d<u32");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:23: expected '>' for sampled texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_F32) {
auto* p = parser("texture_1d<f32>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsSampled());
- ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsF32());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsSampled());
+ ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsF32());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k1d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_I32) {
auto* p = parser("texture_2d<i32>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsSampled());
- ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsI32());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsSampled());
+ ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsI32());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_U32) {
auto* p = parser("texture_3d<u32>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsSampled());
- ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsU32());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k3d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsSampled());
+ ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsU32());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k3d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_Invalid) {
auto* p = parser("texture_1d<abc>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:12: unknown constructed type 'abc'");
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType) {
auto* p = parser("texture_1d<>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:12: invalid subtype for sampled texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan) {
auto* p = parser("texture_1d");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:11: expected '<' for sampled texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingGreaterThan) {
auto* p = parser("texture_1d<u32");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:15: expected '>' for sampled texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_I32) {
auto* p = parser("texture_multisampled_2d<i32>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsMultisampled());
- ASSERT_TRUE(t->AsTexture()->AsMultisampled()->type()->IsI32());
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsMultisampled());
+ ASSERT_TRUE(t.value->AsTexture()->AsMultisampled()->type()->IsI32());
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_Invalid) {
auto* p = parser("texture_multisampled_2d<abc>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:25: unknown constructed type 'abc'");
}
TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_MissingType) {
auto* p = parser("texture_multisampled_2d<>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(t, nullptr);
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:25: invalid subtype for multisampled texture type");
}
TEST_F(ParserImplTest,
TextureSamplerTypes_MultisampledTexture_MissingLessThan) {
auto* p = parser("texture_multisampled_2d");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:24: expected '<' for multisampled texture type");
}
TEST_F(ParserImplTest,
TextureSamplerTypes_MultisampledTexture_MissingGreaterThan) {
auto* p = parser("texture_multisampled_2d<u32");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:28: expected '>' for multisampled texture type");
}
TEST_F(ParserImplTest,
TextureSamplerTypes_StorageTexture_Readonly1dR8Unorm_Old) {
auto* p = parser("texture_ro_1d<r8unorm>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsStorage());
- EXPECT_EQ(t->AsTexture()->AsStorage()->image_format(),
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsStorage());
+ EXPECT_EQ(t.value->AsTexture()->AsStorage()->image_format(),
ast::type::ImageFormat::kR8Unorm);
- EXPECT_EQ(t->AsTexture()->AsStorage()->access(),
+ EXPECT_EQ(t.value->AsTexture()->AsStorage()->access(),
ast::AccessControl::kReadOnly);
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d);
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k1d);
}
TEST_F(ParserImplTest,
TextureSamplerTypes_StorageTexture_Writeonly2dR16Float_Old) {
auto* p = parser("texture_wo_2d<r16float>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsStorage());
- EXPECT_EQ(t->AsTexture()->AsStorage()->image_format(),
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsStorage());
+ EXPECT_EQ(t.value->AsTexture()->AsStorage()->image_format(),
ast::type::ImageFormat::kR16Float);
- EXPECT_EQ(t->AsTexture()->AsStorage()->access(),
+ EXPECT_EQ(t.value->AsTexture()->AsStorage()->access(),
ast::AccessControl::kWriteOnly);
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_InvalidType_Old) {
auto* p = parser("texture_ro_1d<abc>");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:15: invalid format for storage texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingType_Old) {
auto* p = parser("texture_wo_1d<>");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:15: invalid format for storage texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingLessThan_Old) {
auto* p = parser("texture_ro_1d");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:14: expected '<' for storage texture type");
}
TEST_F(ParserImplTest,
TextureSamplerTypes_StorageTexture_MissingGreaterThan_Old) {
auto* p = parser("texture_wo_1d<r8unorm");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:22: expected '>' for storage texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Readonly1dR8Unorm) {
auto* p = parser("texture_storage_ro_1d<r8unorm>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsStorage());
- EXPECT_EQ(t->AsTexture()->AsStorage()->image_format(),
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsStorage());
+ EXPECT_EQ(t.value->AsTexture()->AsStorage()->image_format(),
ast::type::ImageFormat::kR8Unorm);
- EXPECT_EQ(t->AsTexture()->AsStorage()->access(),
+ EXPECT_EQ(t.value->AsTexture()->AsStorage()->access(),
ast::AccessControl::kReadOnly);
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d);
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k1d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Writeonly2dR16Float) {
auto* p = parser("texture_storage_wo_2d<r16float>");
- auto* t = p->texture_sampler_types();
+ auto t = p->texture_sampler_types();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsStorage());
- EXPECT_EQ(t->AsTexture()->AsStorage()->image_format(),
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsStorage());
+ EXPECT_EQ(t.value->AsTexture()->AsStorage()->image_format(),
ast::type::ImageFormat::kR16Float);
- EXPECT_EQ(t->AsTexture()->AsStorage()->access(),
+ EXPECT_EQ(t.value->AsTexture()->AsStorage()->access(),
ast::AccessControl::kWriteOnly);
- EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
+ EXPECT_EQ(t.value->AsTexture()->dim(), ast::type::TextureDimension::k2d);
}
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_InvalidType) {
auto* p = parser("texture_storage_ro_1d<abc>");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:23: invalid format for storage texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingType) {
auto* p = parser("texture_storage_ro_1d<>");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:23: invalid format for storage texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingLessThan) {
auto* p = parser("texture_storage_ro_1d");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:22: expected '<' for storage texture type");
}
TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_MissingGreaterThan) {
auto* p = parser("texture_storage_ro_1d<r8unorm");
- auto* t = p->texture_sampler_types();
- EXPECT_EQ(t, nullptr);
+ auto t = p->texture_sampler_types();
+ EXPECT_EQ(t.value, nullptr);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(t.errored);
EXPECT_EQ(p->error(), "1:30: expected '>' for storage texture type");
}
diff --git a/src/reader/wgsl/parser_impl_type_alias_test.cc b/src/reader/wgsl/parser_impl_type_alias_test.cc
index c580729..df97a4c 100644
--- a/src/reader/wgsl/parser_impl_type_alias_test.cc
+++ b/src/reader/wgsl/parser_impl_type_alias_test.cc
@@ -30,11 +30,13 @@
auto* i32 = tm()->Get(std::make_unique<ast::type::I32Type>());
auto* p = parser("type a = i32");
- auto* t = p->type_alias();
- ASSERT_FALSE(p->has_error());
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsAlias());
- auto* alias = t->AsAlias();
+ auto t = p->type_alias();
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(t.errored);
+ EXPECT_TRUE(t.matched);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsAlias());
+ auto* alias = t.value->AsAlias();
ASSERT_TRUE(alias->type()->IsI32());
ASSERT_EQ(alias->type(), i32);
}
@@ -45,11 +47,13 @@
auto* p = parser("type a = B");
p->register_constructed("B", &str);
- auto* t = p->type_alias();
- ASSERT_FALSE(p->has_error());
- ASSERT_NE(t, nullptr);
- ASSERT_TRUE(t->IsAlias());
- auto* alias = t->AsAlias();
+ auto t = p->type_alias();
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(t.errored);
+ EXPECT_TRUE(t.matched);
+ ASSERT_NE(t.value, nullptr);
+ ASSERT_TRUE(t.value->IsAlias());
+ auto* alias = t.value->AsAlias();
EXPECT_EQ(alias->name(), "a");
ASSERT_TRUE(alias->type()->IsStruct());
@@ -59,33 +63,41 @@
TEST_F(ParserImplTest, TypeDecl_MissingIdent) {
auto* p = parser("type = i32");
- auto* t = p->type_alias();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_alias();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(t.value, nullptr);
EXPECT_EQ(p->error(), "1:6: expected identifier for type alias");
}
TEST_F(ParserImplTest, TypeDecl_InvalidIdent) {
auto* p = parser("type 123 = i32");
- auto* t = p->type_alias();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_alias();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(t.value, nullptr);
EXPECT_EQ(p->error(), "1:6: expected identifier for type alias");
}
TEST_F(ParserImplTest, TypeDecl_MissingEqual) {
auto* p = parser("type a i32");
- auto* t = p->type_alias();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_alias();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(t.value, nullptr);
EXPECT_EQ(p->error(), "1:8: expected '=' for type alias");
}
TEST_F(ParserImplTest, TypeDecl_InvalidType) {
auto* p = parser("type a = B");
- auto* t = p->type_alias();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_alias();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(t.value, nullptr);
EXPECT_EQ(p->error(), "1:10: unknown constructed type 'B'");
}
diff --git a/src/reader/wgsl/parser_impl_type_decl_test.cc b/src/reader/wgsl/parser_impl_type_decl_test.cc
index 20e6b2f..f0cc10d 100644
--- a/src/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_type_decl_test.cc
@@ -37,8 +37,10 @@
TEST_F(ParserImplTest, TypeDecl_Invalid) {
auto* p = parser("1234");
- auto* t = p->type_decl();
- EXPECT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_EQ(t.errored, false);
+ EXPECT_EQ(t.matched, false);
+ EXPECT_EQ(t.value, nullptr);
EXPECT_FALSE(p->has_error());
}
@@ -52,12 +54,14 @@
p->register_constructed("A", alias_type);
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
- EXPECT_EQ(t, alias_type);
- ASSERT_TRUE(t->IsAlias());
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
+ EXPECT_EQ(t.value, alias_type);
+ ASSERT_TRUE(t.value->IsAlias());
- auto* alias = t->AsAlias();
+ auto* alias = t.value->AsAlias();
EXPECT_EQ(alias->name(), "A");
EXPECT_EQ(alias->type(), int_type);
}
@@ -65,8 +69,10 @@
TEST_F(ParserImplTest, TypeDecl_Identifier_NotFound) {
auto* p = parser("B");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:1: unknown constructed type 'B'");
}
@@ -76,10 +82,12 @@
auto* bool_type = tm()->Get(std::make_unique<ast::type::BoolType>());
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
- EXPECT_EQ(t, bool_type);
- ASSERT_TRUE(t->IsBool());
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
+ EXPECT_EQ(t.value, bool_type);
+ ASSERT_TRUE(t.value->IsBool());
}
TEST_F(ParserImplTest, TypeDecl_F32) {
@@ -87,10 +95,12 @@
auto* float_type = tm()->Get(std::make_unique<ast::type::F32Type>());
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
- EXPECT_EQ(t, float_type);
- ASSERT_TRUE(t->IsF32());
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
+ EXPECT_EQ(t.value, float_type);
+ ASSERT_TRUE(t.value->IsF32());
}
TEST_F(ParserImplTest, TypeDecl_I32) {
@@ -98,10 +108,12 @@
auto* int_type = tm()->Get(std::make_unique<ast::type::I32Type>());
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
- EXPECT_EQ(t, int_type);
- ASSERT_TRUE(t->IsI32());
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
+ EXPECT_EQ(t.value, int_type);
+ ASSERT_TRUE(t.value->IsI32());
}
TEST_F(ParserImplTest, TypeDecl_U32) {
@@ -109,10 +121,12 @@
auto* uint_type = tm()->Get(std::make_unique<ast::type::U32Type>());
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
- EXPECT_EQ(t, uint_type);
- ASSERT_TRUE(t->IsU32());
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
+ EXPECT_EQ(t.value, uint_type);
+ ASSERT_TRUE(t.value->IsU32());
}
struct VecData {
@@ -129,11 +143,13 @@
TEST_P(VecTest, Parse) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- EXPECT_TRUE(t->IsVector());
- EXPECT_EQ(t->AsVector()->size(), params.count);
+ EXPECT_TRUE(t.value->IsVector());
+ EXPECT_EQ(t.value->AsVector()->size(), params.count);
}
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
VecTest,
@@ -146,8 +162,10 @@
TEST_P(VecMissingGreaterThanTest, Handles_Missing_GreaterThan) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:9: expected '>' for vector");
}
@@ -162,8 +180,10 @@
TEST_P(VecMissingLessThanTest, Handles_Missing_GreaterThan) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: expected '<' for vector");
}
@@ -178,8 +198,10 @@
TEST_P(VecBadType, Handles_Unknown_Type) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:6: unknown constructed type 'unknown'");
}
@@ -194,8 +216,10 @@
TEST_P(VecMissingType, Handles_Missing_Type) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:6: unable to determine subtype for vector");
}
@@ -207,24 +231,28 @@
TEST_F(ParserImplTest, TypeDecl_Ptr) {
auto* p = parser("ptr<function, f32>");
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- ASSERT_TRUE(t->IsPointer());
+ ASSERT_TRUE(t.value->IsPointer());
- auto* ptr = t->AsPointer();
+ auto* ptr = t.value->AsPointer();
ASSERT_TRUE(ptr->type()->IsF32());
ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
}
TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) {
auto* p = parser("ptr<function, vec2<f32>>");
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- ASSERT_TRUE(t->IsPointer());
+ ASSERT_TRUE(t.value->IsPointer());
- auto* ptr = t->AsPointer();
+ auto* ptr = t.value->AsPointer();
ASSERT_TRUE(ptr->type()->IsVector());
ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
@@ -235,76 +263,94 @@
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingLessThan) {
auto* p = parser("ptr private, f32>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: expected '<' for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingGreaterThan) {
auto* p = parser("ptr<function, f32");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:18: expected '>' for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingComma) {
auto* p = parser("ptr<function f32>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:14: expected ',' for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingStorageClass) {
auto* p = parser("ptr<, f32>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingParams) {
auto* p = parser("ptr<>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_MissingType) {
auto* p = parser("ptr<function,>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:14: missing type for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_BadStorageClass) {
auto* p = parser("ptr<unknown, f32>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: invalid storage class for ptr declaration");
}
TEST_F(ParserImplTest, TypeDecl_Ptr_BadType) {
auto* p = parser("ptr<function, unknown>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:15: unknown constructed type 'unknown'");
}
TEST_F(ParserImplTest, TypeDecl_Array) {
auto* p = parser("array<f32, 5>");
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- ASSERT_TRUE(t->IsArray());
+ ASSERT_TRUE(t.value->IsArray());
- auto* a = t->AsArray();
+ auto* a = t.value->AsArray();
ASSERT_FALSE(a->IsRuntimeArray());
ASSERT_EQ(a->size(), 5u);
ASSERT_TRUE(a->type()->IsF32());
@@ -313,12 +359,14 @@
TEST_F(ParserImplTest, TypeDecl_Array_Stride) {
auto* p = parser("[[stride(16)]] array<f32, 5>");
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- ASSERT_TRUE(t->IsArray());
+ ASSERT_TRUE(t.value->IsArray());
- auto* a = t->AsArray();
+ auto* a = t.value->AsArray();
ASSERT_FALSE(a->IsRuntimeArray());
ASSERT_EQ(a->size(), 5u);
ASSERT_TRUE(a->type()->IsF32());
@@ -328,12 +376,14 @@
TEST_F(ParserImplTest, TypeDecl_Array_Runtime_Stride) {
auto* p = parser("[[stride(16)]] array<f32>");
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- ASSERT_TRUE(t->IsArray());
+ ASSERT_TRUE(t.value->IsArray());
- auto* a = t->AsArray();
+ auto* a = t.value->AsArray();
ASSERT_TRUE(a->IsRuntimeArray());
ASSERT_TRUE(a->type()->IsF32());
ASSERT_TRUE(a->has_array_stride());
@@ -342,12 +392,14 @@
TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_OneBlock) {
auto* p = parser("[[stride(16), stride(32)]] array<f32>");
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- ASSERT_TRUE(t->IsArray());
+ ASSERT_TRUE(t.value->IsArray());
- auto* a = t->AsArray();
+ auto* a = t.value->AsArray();
ASSERT_TRUE(a->IsRuntimeArray());
ASSERT_TRUE(a->type()->IsF32());
@@ -361,12 +413,14 @@
TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_MultipleBlocks) {
auto* p = parser("[[stride(16)]] [[stride(32)]] array<f32>");
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- ASSERT_TRUE(t->IsArray());
+ ASSERT_TRUE(t.value->IsArray());
- auto* a = t->AsArray();
+ auto* a = t.value->AsArray();
ASSERT_TRUE(a->IsRuntimeArray());
ASSERT_TRUE(a->type()->IsF32());
@@ -380,48 +434,60 @@
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_MissingArray) {
auto* p = parser("[[stride(16)]] f32");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:3: unexpected decorations");
}
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_MissingClosingAttr) {
auto* p = parser("[[stride(16) array<f32, 5>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:14: expected ']]' for decoration list");
}
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_UnknownDecoration) {
auto* p = parser("[[unknown 16]] array<f32, 5>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:3: expected decoration");
}
TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingLeftParen) {
auto* p = parser("[[stride 4)]] array<f32, 5>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:10: expected '(' for stride decoration");
}
TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingRightParen) {
auto* p = parser("[[stride(4]] array<f32, 5>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:11: expected ')' for stride decoration");
}
TEST_F(ParserImplTest, TypeDecl_Array_Stride_MissingValue) {
auto* p = parser("[[stride()]] array<f32, 5>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:10: expected signed integer literal for stride decoration");
@@ -429,8 +495,10 @@
TEST_F(ParserImplTest, TypeDecl_Array_Stride_InvalidValue) {
auto* p = parser("[[stride(invalid)]] array<f32, 5>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:10: expected signed integer literal for stride decoration");
@@ -438,76 +506,94 @@
TEST_F(ParserImplTest, TypeDecl_Array_Stride_InvalidValue_Negative) {
auto* p = parser("[[stride(-1)]] array<f32, 5>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:10: stride decoration must be greater than 0");
}
TEST_F(ParserImplTest, TypeDecl_Array_Runtime) {
auto* p = parser("array<u32>");
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- ASSERT_TRUE(t->IsArray());
+ ASSERT_TRUE(t.value->IsArray());
- auto* a = t->AsArray();
+ auto* a = t.value->AsArray();
ASSERT_TRUE(a->IsRuntimeArray());
ASSERT_TRUE(a->type()->IsU32());
}
TEST_F(ParserImplTest, TypeDecl_Array_BadType) {
auto* p = parser("array<unknown, 3>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:7: unknown constructed type 'unknown'");
}
TEST_F(ParserImplTest, TypeDecl_Array_ZeroSize) {
auto* p = parser("array<f32, 0>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:12: array size must be greater than 0");
}
TEST_F(ParserImplTest, TypeDecl_Array_NegativeSize) {
auto* p = parser("array<f32, -1>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:12: array size must be greater than 0");
}
TEST_F(ParserImplTest, TypeDecl_Array_BadSize) {
auto* p = parser("array<f32, invalid>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:12: expected signed integer literal for array size");
}
TEST_F(ParserImplTest, TypeDecl_Array_MissingLessThan) {
auto* p = parser("array f32>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:7: expected '<' for array declaration");
}
TEST_F(ParserImplTest, TypeDecl_Array_MissingGreaterThan) {
auto* p = parser("array<f32");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:10: expected '>' for array declaration");
}
TEST_F(ParserImplTest, TypeDecl_Array_MissingComma) {
auto* p = parser("array<f32 3>");
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:11: expected '>' for array declaration");
}
@@ -527,11 +613,13 @@
TEST_P(MatrixTest, Parse) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
- EXPECT_TRUE(t->IsMatrix());
- auto* mat = t->AsMatrix();
+ EXPECT_TRUE(t.value->IsMatrix());
+ auto* mat = t.value->AsMatrix();
EXPECT_EQ(mat->rows(), params.rows);
EXPECT_EQ(mat->columns(), params.columns);
}
@@ -553,10 +641,12 @@
TEST_P(MatrixMissingGreaterThanTest, Handles_Missing_GreaterThan) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:11: missing > for matrix");
+ ASSERT_EQ(p->error(), "1:11: expected '>' for matrix");
}
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
MatrixMissingGreaterThanTest,
@@ -575,10 +665,12 @@
TEST_P(MatrixMissingLessThanTest, Handles_Missing_GreaterThan) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:8: missing < for matrix");
+ ASSERT_EQ(p->error(), "1:8: expected '<' for matrix");
}
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
MatrixMissingLessThanTest,
@@ -597,8 +689,10 @@
TEST_P(MatrixBadType, Handles_Unknown_Type) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:8: unknown constructed type 'unknown'");
}
@@ -619,8 +713,10 @@
TEST_P(MatrixMissingType, Handles_Missing_Type) {
auto params = GetParam();
auto* p = parser(params.input);
- auto* t = p->type_decl();
- ASSERT_EQ(t, nullptr);
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.errored);
+ EXPECT_FALSE(t.matched);
+ ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:8: unable to determine subtype for matrix");
}
@@ -642,11 +738,13 @@
auto* type = tm()->Get(std::make_unique<ast::type::SamplerType>(
ast::type::SamplerKind::kSampler));
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
- EXPECT_EQ(t, type);
- ASSERT_TRUE(t->IsSampler());
- ASSERT_FALSE(t->AsSampler()->IsComparison());
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
+ EXPECT_EQ(t.value, type);
+ ASSERT_TRUE(t.value->IsSampler());
+ ASSERT_FALSE(t.value->AsSampler()->IsComparison());
}
TEST_F(ParserImplTest, TypeDecl_Texture_Old) {
@@ -656,12 +754,14 @@
auto* type = tm()->Get(std::make_unique<ast::type::SampledTextureType>(
ast::type::TextureDimension::kCube, &f32));
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr) << p->error();
- EXPECT_EQ(t, type);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsSampled());
- ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsF32());
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
+ EXPECT_EQ(t.value, type);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsSampled());
+ ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsF32());
}
TEST_F(ParserImplTest, TypeDecl_Texture) {
@@ -671,12 +771,14 @@
auto* type = tm()->Get(std::make_unique<ast::type::SampledTextureType>(
ast::type::TextureDimension::kCube, &f32));
- auto* t = p->type_decl();
- ASSERT_NE(t, nullptr);
- EXPECT_EQ(t, type);
- ASSERT_TRUE(t->IsTexture());
- ASSERT_TRUE(t->AsTexture()->IsSampled());
- ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsF32());
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr);
+ EXPECT_EQ(t.value, type);
+ ASSERT_TRUE(t.value->IsTexture());
+ ASSERT_TRUE(t.value->AsTexture()->IsSampled());
+ ASSERT_TRUE(t.value->AsTexture()->AsSampled()->type()->IsF32());
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_unary_expression_test.cc b/src/reader/wgsl/parser_impl_unary_expression_test.cc
index 0484162..d9c645c 100644
--- a/src/reader/wgsl/parser_impl_unary_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_unary_expression_test.cc
@@ -29,11 +29,13 @@
TEST_F(ParserImplTest, UnaryExpression_Postix) {
auto* p = parser("a[2]");
auto e = p->unary_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->IsArrayAccessor());
- auto* ary = e->AsArrayAccessor();
+ ASSERT_TRUE(e.value->IsArrayAccessor());
+ auto* ary = e.value->AsArrayAccessor();
ASSERT_TRUE(ary->array()->IsIdentifier());
auto* ident = ary->array()->AsIdentifier();
EXPECT_EQ(ident->name(), "a");
@@ -48,11 +50,13 @@
TEST_F(ParserImplTest, UnaryExpression_Minus) {
auto* p = parser("- 1");
auto e = p->unary_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsUnaryOp());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsUnaryOp());
- auto* u = e->AsUnaryOp();
+ auto* u = e.value->AsUnaryOp();
ASSERT_EQ(u->op(), ast::UnaryOp::kNegation);
ASSERT_TRUE(u->expr()->IsConstructor());
@@ -66,19 +70,23 @@
TEST_F(ParserImplTest, UnaryExpression_Minus_InvalidRHS) {
auto* p = parser("-if(a) {}");
auto e = p->unary_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:2: unable to parse right side of - expression");
}
TEST_F(ParserImplTest, UnaryExpression_Bang) {
auto* p = parser("!1");
auto e = p->unary_expression();
- ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_NE(e, nullptr);
- ASSERT_TRUE(e->IsUnaryOp());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsUnaryOp());
- auto* u = e->AsUnaryOp();
+ auto* u = e.value->AsUnaryOp();
ASSERT_EQ(u->op(), ast::UnaryOp::kNot);
ASSERT_TRUE(u->expr()->IsConstructor());
@@ -92,8 +100,10 @@
TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) {
auto* p = parser("!if (a) {}");
auto e = p->unary_expression();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:2: unable to parse right side of ! expression");
}
diff --git a/src/reader/wgsl/parser_impl_variable_decl_test.cc b/src/reader/wgsl/parser_impl_variable_decl_test.cc
index 35edb24..3ff51ac 100644
--- a/src/reader/wgsl/parser_impl_variable_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decl_test.cc
@@ -25,23 +25,27 @@
TEST_F(ParserImplTest, VariableDecl_Parses) {
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);
- ASSERT_TRUE(var->type()->IsF32());
+ EXPECT_FALSE(p->has_error());
+ EXPECT_TRUE(var.matched);
+ EXPECT_FALSE(var.errored);
+ ASSERT_NE(var.value, nullptr);
+ EXPECT_EQ(var.value->name(), "my_var");
+ EXPECT_NE(var.value->type(), nullptr);
+ EXPECT_TRUE(var.value->type()->IsF32());
- ASSERT_EQ(var->source().range.begin.line, 1u);
- ASSERT_EQ(var->source().range.begin.column, 5u);
- ASSERT_EQ(var->source().range.end.line, 1u);
- ASSERT_EQ(var->source().range.end.column, 11u);
+ EXPECT_EQ(var.value->source().range.begin.line, 1u);
+ EXPECT_EQ(var.value->source().range.begin.column, 5u);
+ EXPECT_EQ(var.value->source().range.end.line, 1u);
+ EXPECT_EQ(var.value->source().range.end.column, 11u);
}
TEST_F(ParserImplTest, VariableDecl_MissingVar) {
auto* p = parser("my_var : f32");
auto v = p->variable_decl();
- ASSERT_EQ(v, nullptr);
- ASSERT_FALSE(p->has_error());
+ EXPECT_EQ(v.value, nullptr);
+ EXPECT_FALSE(v.matched);
+ EXPECT_FALSE(v.errored);
+ EXPECT_FALSE(p->has_error());
auto t = p->next();
ASSERT_TRUE(t.IsIdentifier());
@@ -50,31 +54,37 @@
TEST_F(ParserImplTest, VariableDecl_InvalidIdentDecl) {
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: expected ':' for variable declaration");
+ EXPECT_FALSE(v.matched);
+ EXPECT_TRUE(v.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(v.value, nullptr);
+ EXPECT_EQ(p->error(), "1:12: expected ':' for variable declaration");
}
TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
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());
- EXPECT_EQ(v->storage_class(), ast::StorageClass::kPrivate);
+ EXPECT_TRUE(v.matched);
+ EXPECT_FALSE(v.errored);
+ EXPECT_FALSE(p->has_error());
+ ASSERT_NE(v.value, nullptr);
+ EXPECT_EQ(v.value->name(), "my_var");
+ EXPECT_TRUE(v.value->type()->IsF32());
+ EXPECT_EQ(v.value->storage_class(), ast::StorageClass::kPrivate);
- EXPECT_EQ(v->source().range.begin.line, 1u);
- EXPECT_EQ(v->source().range.begin.column, 14u);
- EXPECT_EQ(v->source().range.end.line, 1u);
- EXPECT_EQ(v->source().range.end.column, 20u);
+ EXPECT_EQ(v.value->source().range.begin.line, 1u);
+ EXPECT_EQ(v.value->source().range.begin.column, 14u);
+ EXPECT_EQ(v.value->source().range.end.line, 1u);
+ EXPECT_EQ(v.value->source().range.end.column, 20u);
}
TEST_F(ParserImplTest, VariableDecl_InvalidStorageClass) {
auto* p = parser("var<unknown> my_var : f32");
auto v = p->variable_decl();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(v, nullptr);
+ EXPECT_FALSE(v.matched);
+ EXPECT_TRUE(v.errored);
+ EXPECT_TRUE(p->has_error());
+ EXPECT_EQ(v.value, nullptr);
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable decoration");
}
diff --git a/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc b/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
index dcbac85..a9271b9 100644
--- a/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
@@ -27,10 +27,12 @@
auto* p = parser(R"([[location(4), builtin(position)]])");
auto decos = p->decoration_list();
ASSERT_FALSE(p->has_error()) << p->error();
- ASSERT_EQ(decos.size(), 2u);
+ ASSERT_FALSE(decos.errored);
+ ASSERT_TRUE(decos.matched);
+ ASSERT_EQ(decos.value.size(), 2u);
- auto deco_0 = ast::As<ast::VariableDecoration>(std::move(decos[0]));
- auto deco_1 = ast::As<ast::VariableDecoration>(std::move(decos[1]));
+ auto deco_0 = ast::As<ast::VariableDecoration>(std::move(decos.value[0]));
+ auto deco_1 = ast::As<ast::VariableDecoration>(std::move(decos.value[1]));
ASSERT_NE(deco_0, nullptr);
ASSERT_NE(deco_1, nullptr);
@@ -43,44 +45,62 @@
TEST_F(ParserImplTest, VariableDecorationList_Empty) {
auto* p = parser(R"([[]])");
auto decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:3: empty decoration list");
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_TRUE(decos.value.empty());
+ EXPECT_EQ(p->error(), "1:3: empty decoration list");
}
TEST_F(ParserImplTest, VariableDecorationList_Invalid) {
auto* p = parser(R"([[invalid]])");
auto decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_TRUE(decos.empty());
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_TRUE(decos.value.empty());
+ EXPECT_EQ(p->error(), "1:3: expected decoration");
}
TEST_F(ParserImplTest, VariableDecorationList_ExtraComma) {
auto* p = parser(R"([[builtin(position), ]])");
auto decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:22: expected decoration");
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_TRUE(decos.value.empty());
+ EXPECT_EQ(p->error(), "1:22: expected decoration");
}
TEST_F(ParserImplTest, VariableDecorationList_MissingComma) {
auto* p = parser(R"([[binding(4) location(5)]])");
auto decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:14: expected ',' for decoration list");
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_TRUE(decos.value.empty());
+ EXPECT_EQ(p->error(), "1:14: expected ',' for decoration list");
}
TEST_F(ParserImplTest, VariableDecorationList_BadDecoration) {
auto* p = parser(R"([[location(bad)]])");
auto decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(),
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_TRUE(decos.value.empty());
+ EXPECT_EQ(p->error(),
"1:12: expected signed integer literal for location decoration");
}
TEST_F(ParserImplTest, VariableDecorationList_InvalidBuiltin) {
auto* p = parser("[[builtin(invalid)]]");
auto decos = p->decoration_list();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:11: invalid value for builtin decoration");
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(decos.errored);
+ EXPECT_FALSE(decos.matched);
+ EXPECT_TRUE(decos.value.empty());
+ EXPECT_EQ(p->error(), "1:11: invalid value for builtin decoration");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_variable_decoration_test.cc b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
index 5ada60c..f99ae14 100644
--- a/src/reader/wgsl/parser_impl_variable_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
@@ -28,8 +28,10 @@
TEST_F(ParserImplTest, VariableDecoration_Location) {
auto* p = parser("location(4)");
auto deco = p->decoration();
- ASSERT_NE(deco, nullptr);
- auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco));
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr);
+ auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco.value));
ASSERT_NE(var_deco, nullptr);
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(var_deco->IsLocation());
@@ -41,24 +43,30 @@
TEST_F(ParserImplTest, VariableDecoration_Location_MissingLeftParen) {
auto* p = parser("location 4)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:10: expected '(' for location decoration");
}
TEST_F(ParserImplTest, VariableDecoration_Location_MissingRightParen) {
auto* p = parser("location(4");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:11: expected ')' for location decoration");
}
TEST_F(ParserImplTest, VariableDecoration_Location_MissingValue) {
auto* p = parser("location()");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:10: expected signed integer literal for location decoration");
}
@@ -66,8 +74,10 @@
TEST_F(ParserImplTest, VariableDecoration_Location_MissingInvalid) {
auto* p = parser("location(nan)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:10: expected signed integer literal for location decoration");
}
@@ -88,8 +98,10 @@
auto* p = parser(std::string("builtin(") + params.input + ")");
auto deco = p->decoration();
- ASSERT_NE(deco, nullptr);
- auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco));
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr);
+ auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco.value));
ASSERT_FALSE(p->has_error()) << p->error();
ASSERT_NE(var_deco, nullptr);
ASSERT_TRUE(var_deco->IsBuiltin());
@@ -115,48 +127,60 @@
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingLeftParen) {
auto* p = parser("builtin position)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: expected '(' for builtin decoration");
}
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingRightParen) {
auto* p = parser("builtin(position");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:17: expected ')' for builtin decoration");
}
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingValue) {
auto* p = parser("builtin()");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
}
TEST_F(ParserImplTest, VariableDecoration_Builtin_InvalidValue) {
auto* p = parser("builtin(other_thingy)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: invalid value for builtin decoration");
}
TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingInvalid) {
auto* p = parser("builtin(3)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
}
TEST_F(ParserImplTest, VariableDecoration_Binding) {
auto* p = parser("binding(4)");
auto deco = p->decoration();
- ASSERT_NE(deco, nullptr);
- auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco));
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr);
+ auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco.value));
ASSERT_NE(var_deco, nullptr);
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(var_deco->IsBinding());
@@ -168,24 +192,30 @@
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingLeftParen) {
auto* p = parser("binding 4)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: expected '(' for binding decoration");
}
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingRightParen) {
auto* p = parser("binding(4");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:10: expected ')' for binding decoration");
}
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingValue) {
auto* p = parser("binding()");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:9: expected signed integer literal for binding decoration");
}
@@ -193,8 +223,10 @@
TEST_F(ParserImplTest, VariableDecoration_Binding_MissingInvalid) {
auto* p = parser("binding(nan)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:9: expected signed integer literal for binding decoration");
}
@@ -202,8 +234,10 @@
TEST_F(ParserImplTest, VariableDecoration_set) {
auto* p = parser("set(4)");
auto deco = p->decoration();
- ASSERT_NE(deco, nullptr);
- auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco));
+ EXPECT_TRUE(deco.matched);
+ EXPECT_FALSE(deco.errored);
+ ASSERT_NE(deco.value, nullptr);
+ auto var_deco = ast::As<ast::VariableDecoration>(std::move(deco.value));
ASSERT_FALSE(p->has_error());
ASSERT_NE(var_deco.get(), nullptr);
ASSERT_TRUE(var_deco->IsSet());
@@ -215,24 +249,30 @@
TEST_F(ParserImplTest, VariableDecoration_Set_MissingLeftParen) {
auto* p = parser("set 2)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:5: expected '(' for set decoration");
}
TEST_F(ParserImplTest, VariableDecoration_Set_MissingRightParen) {
auto* p = parser("set(2");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:6: expected ')' for set decoration");
}
TEST_F(ParserImplTest, VariableDecoration_Set_MissingValue) {
auto* p = parser("set()");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:5: expected signed integer literal for set decoration");
}
@@ -240,8 +280,10 @@
TEST_F(ParserImplTest, VariableDecoration_Set_MissingInvalid) {
auto* p = parser("set(nan)");
auto deco = p->decoration();
- ASSERT_EQ(deco, nullptr);
- ASSERT_TRUE(p->has_error());
+ EXPECT_FALSE(deco.matched);
+ EXPECT_TRUE(deco.errored);
+ EXPECT_EQ(deco.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:5: expected signed integer literal for set decoration");
}
diff --git a/src/reader/wgsl/parser_impl_variable_stmt_test.cc b/src/reader/wgsl/parser_impl_variable_stmt_test.cc
index 8a984c9..a0fba95 100644
--- a/src/reader/wgsl/parser_impl_variable_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_stmt_test.cc
@@ -26,96 +26,114 @@
TEST_F(ParserImplTest, VariableStmt_VariableDecl) {
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->IsVariableDecl());
- ASSERT_NE(e->variable(), nullptr);
- EXPECT_EQ(e->variable()->name(), "a");
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsVariableDecl());
+ ASSERT_NE(e.value->variable(), nullptr);
+ EXPECT_EQ(e.value->variable()->name(), "a");
- ASSERT_EQ(e->source().range.begin.line, 1u);
- ASSERT_EQ(e->source().range.begin.column, 5u);
- ASSERT_EQ(e->source().range.end.line, 1u);
- ASSERT_EQ(e->source().range.end.column, 6u);
+ ASSERT_EQ(e.value->source().range.begin.line, 1u);
+ ASSERT_EQ(e.value->source().range.begin.column, 5u);
+ ASSERT_EQ(e.value->source().range.end.line, 1u);
+ ASSERT_EQ(e.value->source().range.end.column, 6u);
- EXPECT_EQ(e->variable()->constructor(), nullptr);
+ EXPECT_EQ(e.value->variable()->constructor(), nullptr);
}
TEST_F(ParserImplTest, VariableStmt_VariableDecl_WithInit) {
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->IsVariableDecl());
- ASSERT_NE(e->variable(), nullptr);
- EXPECT_EQ(e->variable()->name(), "a");
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsVariableDecl());
+ ASSERT_NE(e.value->variable(), nullptr);
+ EXPECT_EQ(e.value->variable()->name(), "a");
- ASSERT_EQ(e->source().range.begin.line, 1u);
- ASSERT_EQ(e->source().range.begin.column, 5u);
- ASSERT_EQ(e->source().range.end.line, 1u);
- ASSERT_EQ(e->source().range.end.column, 6u);
+ ASSERT_EQ(e.value->source().range.begin.line, 1u);
+ ASSERT_EQ(e.value->source().range.begin.column, 5u);
+ ASSERT_EQ(e.value->source().range.end.line, 1u);
+ ASSERT_EQ(e.value->source().range.end.column, 6u);
- ASSERT_NE(e->variable()->constructor(), nullptr);
- EXPECT_TRUE(e->variable()->constructor()->IsConstructor());
+ ASSERT_NE(e.value->variable()->constructor(), nullptr);
+ EXPECT_TRUE(e.value->variable()->constructor()->IsConstructor());
}
TEST_F(ParserImplTest, VariableStmt_VariableDecl_Invalid) {
auto* p = parser("var a : invalid;");
auto e = p->variable_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:9: unknown constructed type 'invalid'");
}
TEST_F(ParserImplTest, VariableStmt_VariableDecl_ConstructorInvalid) {
auto* p = parser("var a : i32 = if(a) {}");
auto e = p->variable_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:15: missing constructor for variable declaration");
}
TEST_F(ParserImplTest, VariableStmt_Const) {
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->IsVariableDecl());
+ EXPECT_TRUE(e.matched);
+ EXPECT_FALSE(e.errored);
+ EXPECT_FALSE(p->has_error()) << p->error();
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e.value->IsVariableDecl());
- ASSERT_EQ(e->source().range.begin.line, 1u);
- ASSERT_EQ(e->source().range.begin.column, 7u);
- ASSERT_EQ(e->source().range.end.line, 1u);
- ASSERT_EQ(e->source().range.end.column, 8u);
+ ASSERT_EQ(e.value->source().range.begin.line, 1u);
+ ASSERT_EQ(e.value->source().range.begin.column, 7u);
+ ASSERT_EQ(e.value->source().range.end.line, 1u);
+ ASSERT_EQ(e.value->source().range.end.column, 8u);
}
TEST_F(ParserImplTest, VariableStmt_Const_InvalidVarIdent) {
auto* p = parser("const a : invalid = 1");
auto e = p->variable_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:11: unknown constructed type 'invalid'");
}
TEST_F(ParserImplTest, VariableStmt_Const_MissingEqual) {
auto* p = parser("const a : i32 1");
auto e = p->variable_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:15: expected '=' for constant declaration");
}
TEST_F(ParserImplTest, VariableStmt_Const_MissingConstructor) {
auto* p = parser("const a : i32 =");
auto e = p->variable_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:16: missing constructor for const declaration");
}
TEST_F(ParserImplTest, VariableStmt_Const_InvalidConstructor) {
auto* p = parser("const a : i32 = if (a) {}");
auto e = p->variable_stmt();
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(e, nullptr);
+ EXPECT_FALSE(e.matched);
+ EXPECT_TRUE(e.errored);
+ EXPECT_EQ(e.value, nullptr);
+ EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:17: missing constructor for const declaration");
}
diff --git a/src/reader/wgsl/parser_impl_variable_storage_decoration_test.cc b/src/reader/wgsl/parser_impl_variable_storage_decoration_test.cc
index 70e7a63..75daebf 100644
--- a/src/reader/wgsl/parser_impl_variable_storage_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_storage_decoration_test.cc
@@ -39,8 +39,10 @@
auto* p = parser(std::string("<") + params.input + ">");
auto sc = p->variable_storage_decoration();
- ASSERT_FALSE(p->has_error());
- EXPECT_EQ(sc, params.result);
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(sc.errored);
+ EXPECT_TRUE(sc.matched);
+ EXPECT_EQ(sc.value, params.result);
auto t = p->next();
EXPECT_TRUE(t.IsEof());
@@ -64,24 +66,27 @@
TEST_F(ParserImplTest, VariableStorageDecoration_NoMatch) {
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");
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(sc.errored);
+ EXPECT_FALSE(sc.matched);
+ EXPECT_EQ(p->error(), "1:2: invalid storage class for variable decoration");
}
TEST_F(ParserImplTest, VariableStorageDecoration_Empty) {
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");
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(sc.errored);
+ EXPECT_FALSE(sc.matched);
+ EXPECT_EQ(p->error(), "1:2: invalid storage class for variable decoration");
}
TEST_F(ParserImplTest, VariableStorageDecoration_MissingLessThan) {
auto* p = parser("in>");
auto sc = p->variable_storage_decoration();
- ASSERT_EQ(sc, ast::StorageClass::kNone);
- ASSERT_FALSE(p->has_error());
+ EXPECT_FALSE(p->has_error());
+ EXPECT_FALSE(sc.errored);
+ EXPECT_FALSE(sc.matched);
auto t = p->next();
ASSERT_TRUE(t.IsIn());
@@ -90,9 +95,10 @@
TEST_F(ParserImplTest, VariableStorageDecoration_MissingGreaterThan) {
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: expected '>' for variable decoration");
+ EXPECT_TRUE(p->has_error());
+ EXPECT_TRUE(sc.errored);
+ EXPECT_FALSE(sc.matched);
+ EXPECT_EQ(p->error(), "1:4: expected '>' for variable decoration");
}
} // namespace