wsgl parser: expect for variable_ident_decl
All the call sites of `variable_ident_decl()` add their own error handling, so transform this into `expect_variable_ident_decl()`. Also makes error messages more consistent. Bug: tint:282 Change-Id: I0b5ac984018ba78896ddec0320636f5b5c4ad0b2 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32100 Reviewed-by: dan sinclair <dsinclair@chromium.org> Commit-Queue: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
6512327f01
commit
b8df12042a
|
@ -123,7 +123,7 @@ ParserImpl::ParserImpl(Context* ctx, Source::File const* file)
|
||||||
|
|
||||||
ParserImpl::~ParserImpl() = default;
|
ParserImpl::~ParserImpl() = default;
|
||||||
|
|
||||||
void ParserImpl::add_error(const Token& t,
|
void ParserImpl::add_error(const Source& source,
|
||||||
const std::string& err,
|
const std::string& err,
|
||||||
const std::string& use) {
|
const std::string& use) {
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
|
@ -131,7 +131,7 @@ void ParserImpl::add_error(const Token& t,
|
||||||
if (!use.empty()) {
|
if (!use.empty()) {
|
||||||
msg << " for " << use;
|
msg << " for " << use;
|
||||||
}
|
}
|
||||||
add_error(t, msg.str());
|
add_error(source, msg.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParserImpl::add_error(const Token& t, const std::string& err) {
|
void ParserImpl::add_error(const Token& t, const std::string& err) {
|
||||||
|
@ -317,27 +317,23 @@ std::unique_ptr<ast::Variable> ParserImpl::global_constant_decl() {
|
||||||
if (!match(Token::Type::kConst))
|
if (!match(Token::Type::kConst))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto decl = variable_ident_decl();
|
const char* use = "constant declaration";
|
||||||
|
|
||||||
|
auto decl = expect_variable_ident_decl(use);
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (decl.name.empty() || decl.type == nullptr) {
|
|
||||||
add_error(peek(), "error parsing constant variable identifier");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto var = std::make_unique<ast::Variable>(
|
auto var = std::make_unique<ast::Variable>(
|
||||||
decl.source, decl.name, ast::StorageClass::kNone, decl.type);
|
decl.source, decl.name, ast::StorageClass::kNone, decl.type);
|
||||||
var->set_is_const(true);
|
var->set_is_const(true);
|
||||||
|
|
||||||
auto t = next();
|
if (!expect(use, Token::Type::kEqual))
|
||||||
if (!t.IsEqual()) {
|
|
||||||
add_error(t, "missing = for const declaration");
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
auto init = expect_const_expr();
|
auto init = expect_const_expr();
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
var->set_constructor(std::move(init));
|
var->set_constructor(std::move(init));
|
||||||
|
|
||||||
return var;
|
return var;
|
||||||
|
@ -351,15 +347,11 @@ std::unique_ptr<ast::Variable> ParserImpl::variable_decl() {
|
||||||
|
|
||||||
auto sc = variable_storage_decoration();
|
auto sc = variable_storage_decoration();
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return {};
|
return nullptr;
|
||||||
|
|
||||||
auto decl = variable_ident_decl();
|
auto decl = expect_variable_ident_decl("variable declaration");
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (decl.name.empty() || decl.type == nullptr) {
|
|
||||||
add_error(peek(), "invalid identifier declaration");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_unique<ast::Variable>(decl.source, decl.name, sc, decl.type);
|
return std::make_unique<ast::Variable>(decl.source, decl.name, sc, decl.type);
|
||||||
}
|
}
|
||||||
|
@ -753,26 +745,22 @@ ast::type::ImageFormat ParserImpl::image_storage_type() {
|
||||||
|
|
||||||
// variable_ident_decl
|
// variable_ident_decl
|
||||||
// : IDENT COLON type_decl
|
// : IDENT COLON type_decl
|
||||||
ParserImpl::TypedIdentifier ParserImpl::variable_ident_decl() {
|
ParserImpl::TypedIdentifier ParserImpl::expect_variable_ident_decl(
|
||||||
|
const std::string& use) {
|
||||||
|
std::string name;
|
||||||
|
Source source;
|
||||||
|
if (!expect_ident(use, &name, &source))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (!expect(use, Token::Type::kColon))
|
||||||
|
return {};
|
||||||
|
|
||||||
auto t = peek();
|
auto t = peek();
|
||||||
if (!t.IsIdentifier())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
auto name = t.to_str();
|
|
||||||
auto source = t.source();
|
|
||||||
next(); // Consume the peek
|
|
||||||
|
|
||||||
t = next();
|
|
||||||
if (!t.IsColon()) {
|
|
||||||
add_error(t, "missing : for identifier declaration");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* type = type_decl();
|
auto* type = type_decl();
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return {};
|
return {};
|
||||||
if (type == nullptr) {
|
if (type == nullptr) {
|
||||||
add_error(peek(), "invalid type for identifier declaration");
|
add_error(t.source(), "invalid type", use);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,9 +882,8 @@ ast::type::Type* ParserImpl::type_decl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto decos = decoration_list();
|
auto decos = decoration_list();
|
||||||
if (has_error()) {
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if (match(Token::Type::kArray)) {
|
if (match(Token::Type::kArray)) {
|
||||||
auto array_decos = cast_decorations<ast::ArrayDecoration>(decos);
|
auto array_decos = cast_decorations<ast::ArrayDecoration>(decos);
|
||||||
|
@ -1133,9 +1120,8 @@ std::unique_ptr<ast::type::StructType> ParserImpl::struct_decl(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto body = expect_struct_body_decl();
|
auto body = expect_struct_body_decl();
|
||||||
if (has_error()) {
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_unique<ast::type::StructType>(
|
return std::make_unique<ast::type::StructType>(
|
||||||
name, std::make_unique<ast::Struct>(source, std::move(struct_decos),
|
name, std::make_unique<ast::Struct>(source, std::move(struct_decos),
|
||||||
|
@ -1150,6 +1136,8 @@ ast::StructMemberList ParserImpl::expect_struct_body_decl() {
|
||||||
|
|
||||||
while (!peek().IsBraceRight() && !peek().IsEof()) {
|
while (!peek().IsBraceRight() && !peek().IsEof()) {
|
||||||
auto decos = decoration_list();
|
auto decos = decoration_list();
|
||||||
|
if (has_error())
|
||||||
|
return ast::StructMemberList{};
|
||||||
|
|
||||||
auto mem = expect_struct_member(decos);
|
auto mem = expect_struct_member(decos);
|
||||||
if (has_error())
|
if (has_error())
|
||||||
|
@ -1166,15 +1154,23 @@ ast::StructMemberList ParserImpl::expect_struct_body_decl() {
|
||||||
// : struct_member_decoration_decl+ variable_ident_decl SEMICOLON
|
// : struct_member_decoration_decl+ variable_ident_decl SEMICOLON
|
||||||
std::unique_ptr<ast::StructMember> ParserImpl::expect_struct_member(
|
std::unique_ptr<ast::StructMember> ParserImpl::expect_struct_member(
|
||||||
ast::DecorationList& decos) {
|
ast::DecorationList& decos) {
|
||||||
auto t = peek();
|
// FUDGE - Abort early if we enter with an error state to avoid accumulating
|
||||||
|
// multiple error messages. This is a work around for the unit tests that
|
||||||
auto decl = variable_ident_decl();
|
// call:
|
||||||
|
// auto decos = p->decoration_list();
|
||||||
|
// auto m = p->expect_struct_member(decos);
|
||||||
|
// ... and expect a single error message due to bad decorations.
|
||||||
|
// While expect_struct_body_decl() aborts after checking for decoration parse
|
||||||
|
// errors (and so these tests do not currently reflect full-parse behaviour),
|
||||||
|
// they do test the long-term desired behavior where the parser can
|
||||||
|
// resynchronize at the ']]'.
|
||||||
|
// TODO(ben-clayton) - remove this once resynchronization is implemented.
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (decl.name.empty() || decl.type == nullptr) {
|
|
||||||
add_error(peek(), "invalid identifier declaration");
|
auto decl = expect_variable_ident_decl("struct member");
|
||||||
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
auto member_decos = cast_decorations<ast::StructMemberDecoration>(decos);
|
auto member_decos = cast_decorations<ast::StructMemberDecoration>(decos);
|
||||||
|
|
||||||
|
@ -1255,16 +1251,14 @@ std::unique_ptr<ast::Function> ParserImpl::function_header() {
|
||||||
// :
|
// :
|
||||||
// | (variable_ident_decl COMMA)* variable_ident_decl
|
// | (variable_ident_decl COMMA)* variable_ident_decl
|
||||||
ast::VariableList ParserImpl::expect_param_list() {
|
ast::VariableList ParserImpl::expect_param_list() {
|
||||||
auto t = peek();
|
if (!peek().IsIdentifier()) // Empty list
|
||||||
|
return ast::VariableList{};
|
||||||
|
|
||||||
ast::VariableList ret;
|
auto decl = expect_variable_ident_decl("parameter");
|
||||||
|
|
||||||
auto decl = variable_ident_decl();
|
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return {};
|
return {};
|
||||||
if (decl.name.empty() || decl.type == nullptr)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
|
ast::VariableList ret;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto var = std::make_unique<ast::Variable>(
|
auto var = std::make_unique<ast::Variable>(
|
||||||
decl.source, decl.name, ast::StorageClass::kNone, decl.type);
|
decl.source, decl.name, ast::StorageClass::kNone, decl.type);
|
||||||
|
@ -1275,19 +1269,12 @@ ast::VariableList ParserImpl::expect_param_list() {
|
||||||
var->set_is_const(true);
|
var->set_is_const(true);
|
||||||
ret.push_back(std::move(var));
|
ret.push_back(std::move(var));
|
||||||
|
|
||||||
t = peek();
|
if (!match(Token::Type::kComma))
|
||||||
if (!t.IsComma())
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
next(); // Consume the peek
|
decl = expect_variable_ident_decl("parameter");
|
||||||
|
|
||||||
decl = variable_ident_decl();
|
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return {};
|
return {};
|
||||||
if (decl.name.empty() || decl.type == nullptr) {
|
|
||||||
add_error(t, "found , but no variable declaration");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1518,19 +1505,12 @@ std::unique_ptr<ast::VariableDeclStatement> ParserImpl::variable_stmt() {
|
||||||
if (t.IsConst()) {
|
if (t.IsConst()) {
|
||||||
next(); // Consume the peek
|
next(); // Consume the peek
|
||||||
|
|
||||||
auto decl = variable_ident_decl();
|
auto decl = expect_variable_ident_decl("constant declaration");
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (decl.name.empty() || decl.type == nullptr) {
|
|
||||||
add_error(peek(), "unable to parse variable declaration");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
t = next();
|
if (!expect("constant declaration", Token::Type::kEqual))
|
||||||
if (!t.IsEqual()) {
|
|
||||||
add_error(t, "missing = for constant declaration");
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
auto constructor = logical_or_expression();
|
auto constructor = logical_or_expression();
|
||||||
if (has_error())
|
if (has_error())
|
||||||
|
@ -2760,9 +2740,9 @@ bool ParserImpl::decoration_bracketed_list(ast::DecorationList& decos) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto t = peek();
|
Source source;
|
||||||
if (match(Token::Type::kAttrRight)) {
|
if (match(Token::Type::kAttrRight, &source)) {
|
||||||
add_error(t, "empty decoration list");
|
add_error(source, "empty decoration list");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2954,7 +2934,7 @@ bool ParserImpl::expect(const std::string& use, Token::Type tok) {
|
||||||
bool ParserImpl::expect_sint(const std::string& use, int32_t* out) {
|
bool ParserImpl::expect_sint(const std::string& use, int32_t* out) {
|
||||||
auto t = next();
|
auto t = next();
|
||||||
if (!t.IsSintLiteral()) {
|
if (!t.IsSintLiteral()) {
|
||||||
add_error(t, "expected signed integer literal", use);
|
add_error(t.source(), "expected signed integer literal", use);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*out = t.to_i32();
|
*out = t.to_i32();
|
||||||
|
@ -2999,7 +2979,7 @@ bool ParserImpl::expect_ident(const std::string& use,
|
||||||
*source = t.source();
|
*source = t.source();
|
||||||
|
|
||||||
if (!t.IsIdentifier()) {
|
if (!t.IsIdentifier()) {
|
||||||
add_error(t, "expected identifier", use);
|
add_error(t.source(), "expected identifier", use);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,11 +132,11 @@ class ParserImpl {
|
||||||
/// @param msg the error message
|
/// @param msg the error message
|
||||||
void add_error(const Token& t, const std::string& msg);
|
void add_error(const Token& t, const std::string& msg);
|
||||||
/// Appends an error raised when parsing |use| at |t| with the message |msg|
|
/// Appends an error raised when parsing |use| at |t| with the message |msg|
|
||||||
/// @param t the token to associate the error with
|
/// @param source the source to associate the error with
|
||||||
/// @param msg the error message
|
/// @param msg the error message
|
||||||
/// @param use a description of what was being parsed when the error was
|
/// @param use a description of what was being parsed when the error was
|
||||||
/// raised.
|
/// raised.
|
||||||
void add_error(const Token& t,
|
void add_error(const Source& source,
|
||||||
const std::string& msg,
|
const std::string& msg,
|
||||||
const std::string& use);
|
const std::string& use);
|
||||||
/// Appends an error at |source| with the message |msg|
|
/// Appends an error at |source| with the message |msg|
|
||||||
|
@ -169,9 +169,11 @@ class ParserImpl {
|
||||||
/// Parses a `variable_decl` grammar element
|
/// Parses a `variable_decl` grammar element
|
||||||
/// @returns the parsed variable or nullptr otherwise
|
/// @returns the parsed variable or nullptr otherwise
|
||||||
std::unique_ptr<ast::Variable> variable_decl();
|
std::unique_ptr<ast::Variable> variable_decl();
|
||||||
/// Parses a `variable_ident_decl` grammar element
|
/// 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.
|
||||||
/// @returns the identifier and type parsed or empty otherwise
|
/// @returns the identifier and type parsed or empty otherwise
|
||||||
TypedIdentifier variable_ident_decl();
|
TypedIdentifier expect_variable_ident_decl(const std::string& use);
|
||||||
/// Parses a `variable_storage_decoration` grammar element
|
/// Parses a `variable_storage_decoration` grammar element
|
||||||
/// @returns the storage class or StorageClass::kNone if none matched
|
/// @returns the storage class or StorageClass::kNone if none matched
|
||||||
ast::StorageClass variable_storage_decoration();
|
ast::StorageClass variable_storage_decoration();
|
||||||
|
|
|
@ -169,14 +169,14 @@ TEST_F(ParserImplErrorTest, ConstructorExprMissingRParen) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, ConstVarStmtInvalid) {
|
TEST_F(ParserImplErrorTest, ConstVarStmtInvalid) {
|
||||||
EXPECT("fn f() -> void { const >; }",
|
EXPECT("fn f() -> void { const >; }",
|
||||||
"test.wgsl:1:24 error: unable to parse variable declaration\n"
|
"test.wgsl:1:24 error: expected identifier for constant declaration\n"
|
||||||
"fn f() -> void { const >; }\n"
|
"fn f() -> void { const >; }\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, ConstVarStmtMissingAssignment) {
|
TEST_F(ParserImplErrorTest, ConstVarStmtMissingAssignment) {
|
||||||
EXPECT("fn f() -> void { const a : i32; }",
|
EXPECT("fn f() -> void { const a : i32; }",
|
||||||
"test.wgsl:1:31 error: missing = for constant declaration\n"
|
"test.wgsl:1:31 error: expected '=' for constant declaration\n"
|
||||||
"fn f() -> void { const a : i32; }\n"
|
"fn f() -> void { const a : i32; }\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
@ -416,23 +416,23 @@ TEST_F(ParserImplErrorTest, FunctionDeclInvalidReturnType) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclParamMissingColon) {
|
TEST_F(ParserImplErrorTest, FunctionDeclParamMissingColon) {
|
||||||
EXPECT("fn f(x) -> void {}",
|
EXPECT("fn f(x) -> void {}",
|
||||||
"test.wgsl:1:7 error: missing : for identifier declaration\n"
|
"test.wgsl:1:7 error: expected ':' for parameter\n"
|
||||||
"fn f(x) -> void {}\n"
|
"fn f(x) -> void {}\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclParamInvalidType) {
|
TEST_F(ParserImplErrorTest, FunctionDeclParamInvalidType) {
|
||||||
EXPECT("fn f(x : 1) -> void {}",
|
EXPECT("fn f(x : 1) -> void {}",
|
||||||
"test.wgsl:1:10 error: invalid type for identifier declaration\n"
|
"test.wgsl:1:10 error: invalid type for parameter\n"
|
||||||
"fn f(x : 1) -> void {}\n"
|
"fn f(x : 1) -> void {}\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclParamMissing) {
|
TEST_F(ParserImplErrorTest, FunctionDeclParamMissing) {
|
||||||
EXPECT("fn f(x : i32, ) -> void {}",
|
EXPECT("fn f(x : i32, ) -> void {}",
|
||||||
"test.wgsl:1:13 error: found , but no variable declaration\n"
|
"test.wgsl:1:15 error: expected identifier for parameter\n"
|
||||||
"fn f(x : i32, ) -> void {}\n"
|
"fn f(x : i32, ) -> void {}\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclMissingLBrace) {
|
TEST_F(ParserImplErrorTest, FunctionDeclMissingLBrace) {
|
||||||
|
@ -451,7 +451,7 @@ TEST_F(ParserImplErrorTest, FunctionDeclMissingRBrace) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclConstInvalidIdentifier) {
|
TEST_F(ParserImplErrorTest, GlobalDeclConstInvalidIdentifier) {
|
||||||
EXPECT("const ^ : i32 = 1;",
|
EXPECT("const ^ : i32 = 1;",
|
||||||
"test.wgsl:1:7 error: error parsing constant variable identifier\n"
|
"test.wgsl:1:7 error: expected identifier for constant declaration\n"
|
||||||
"const ^ : i32 = 1;\n"
|
"const ^ : i32 = 1;\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
@ -479,7 +479,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclConstMissingRParen) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclConstMissingAssignment) {
|
TEST_F(ParserImplErrorTest, GlobalDeclConstMissingAssignment) {
|
||||||
EXPECT("const i : vec2<i32>;",
|
EXPECT("const i : vec2<i32>;",
|
||||||
"test.wgsl:1:20 error: missing = for const declaration\n"
|
"test.wgsl:1:20 error: expected '=' for constant declaration\n"
|
||||||
"const i : vec2<i32>;\n"
|
"const i : vec2<i32>;\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
@ -702,7 +702,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclStructMemberDecoMissingEnd) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclStructMemberInvalidIdentifier) {
|
TEST_F(ParserImplErrorTest, GlobalDeclStructMemberInvalidIdentifier) {
|
||||||
EXPECT("struct S { 1 : i32; };",
|
EXPECT("struct S { 1 : i32; };",
|
||||||
"test.wgsl:1:12 error: invalid identifier declaration\n"
|
"test.wgsl:1:12 error: expected identifier for struct member\n"
|
||||||
"struct S { 1 : i32; };\n"
|
"struct S { 1 : i32; };\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
@ -988,7 +988,7 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarDecoBindingSetValue) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarInvalidIdentifier) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarInvalidIdentifier) {
|
||||||
EXPECT("var ^ : mat4x4;",
|
EXPECT("var ^ : mat4x4;",
|
||||||
"test.wgsl:1:5 error: invalid identifier declaration\n"
|
"test.wgsl:1:5 error: expected identifier for variable declaration\n"
|
||||||
"var ^ : mat4x4;\n"
|
"var ^ : mat4x4;\n"
|
||||||
" ^\n");
|
" ^\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ TEST_F(ForStmtErrorTest, MissingRightBrace) {
|
||||||
// Test a for loop with an invalid initializer statement.
|
// Test a for loop with an invalid initializer statement.
|
||||||
TEST_F(ForStmtErrorTest, InvalidInitializerAsConstDecl) {
|
TEST_F(ForStmtErrorTest, InvalidInitializerAsConstDecl) {
|
||||||
std::string for_str = "for (const x: i32;;) { }";
|
std::string for_str = "for (const x: i32;;) { }";
|
||||||
std::string error_str = "1:18: missing = for constant declaration";
|
std::string error_str = "1:18: expected '=' for constant declaration";
|
||||||
|
|
||||||
TestForWithError(for_str, error_str);
|
TestForWithError(for_str, error_str);
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,7 @@ TEST_F(ForStmtErrorTest, InvalidContinuingMatch) {
|
||||||
// Test a for loop with an invalid body.
|
// Test a for loop with an invalid body.
|
||||||
TEST_F(ForStmtErrorTest, InvalidBody) {
|
TEST_F(ForStmtErrorTest, InvalidBody) {
|
||||||
std::string for_str = "for (;;) { const x: i32; }";
|
std::string for_str = "for (;;) { const x: i32; }";
|
||||||
std::string error_str = "1:24: missing = for constant declaration";
|
std::string error_str = "1:24: expected '=' for constant declaration";
|
||||||
|
|
||||||
TestForWithError(for_str, error_str);
|
TestForWithError(for_str, error_str);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ TEST_F(ParserImplTest, FunctionHeader_InvalidParamList) {
|
||||||
auto f = p->function_header();
|
auto f = p->function_header();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(f, nullptr);
|
ASSERT_EQ(f, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:15: found , but no variable declaration");
|
EXPECT_EQ(p->error(), "1:16: expected identifier for parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionHeader_MissingParenRight) {
|
TEST_F(ParserImplTest, FunctionHeader_MissingParenRight) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) {
|
||||||
auto e = p->global_constant_decl();
|
auto e = p->global_constant_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_EQ(e, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:14: missing = for const declaration");
|
EXPECT_EQ(p->error(), "1:14: expected '=' for constant declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
|
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
|
||||||
|
|
|
@ -71,7 +71,7 @@ TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_Invalid) {
|
||||||
auto* p = parser("const a : vec2<i32>;");
|
auto* p = parser("const a : vec2<i32>;");
|
||||||
p->expect_global_decl();
|
p->expect_global_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:20: missing = for const declaration");
|
EXPECT_EQ(p->error(), "1:20: expected '=' for constant declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_MissingSemicolon) {
|
TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_MissingSemicolon) {
|
||||||
|
|
|
@ -87,7 +87,7 @@ TEST_F(ParserImplTest, ParamList_Multiple) {
|
||||||
TEST_F(ParserImplTest, ParamList_Empty) {
|
TEST_F(ParserImplTest, ParamList_Empty) {
|
||||||
auto* p = parser("");
|
auto* p = parser("");
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error());
|
||||||
EXPECT_EQ(e.size(), 0u);
|
EXPECT_EQ(e.size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ TEST_F(ParserImplTest, ParamList_HangingComma) {
|
||||||
auto* p = parser("a : i32,");
|
auto* p = parser("a : i32,");
|
||||||
auto e = p->expect_param_list();
|
auto e = p->expect_param_list();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:8: found , but no variable declaration");
|
EXPECT_EQ(p->error(), "1:9: expected identifier for parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -70,7 +70,7 @@ TEST_F(ParserImplTest, StructBodyDecl_InvalidToken) {
|
||||||
} )");
|
} )");
|
||||||
auto m = p->expect_struct_body_decl();
|
auto m = p->expect_struct_body_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "4:3: invalid identifier declaration");
|
EXPECT_EQ(p->error(), "4:3: expected identifier for struct member");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -52,7 +52,7 @@ TEST_F(ParserImplTest, VariableDecl_InvalidIdentDecl) {
|
||||||
auto v = p->variable_decl();
|
auto v = p->variable_decl();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(v, nullptr);
|
ASSERT_EQ(v, nullptr);
|
||||||
ASSERT_EQ(p->error(), "1:12: missing : for identifier declaration");
|
ASSERT_EQ(p->error(), "1:12: expected ':' for variable declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
|
TEST_F(ParserImplTest, VariableDecl_WithStorageClass) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_Parses) {
|
TEST_F(ParserImplTest, VariableIdentDecl_Parses) {
|
||||||
auto* p = parser("my_var : f32");
|
auto* p = parser("my_var : f32");
|
||||||
auto decl = p->variable_ident_decl();
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_FALSE(p->has_error());
|
||||||
ASSERT_EQ(decl.name, "my_var");
|
ASSERT_EQ(decl.name, "my_var");
|
||||||
ASSERT_NE(decl.type, nullptr);
|
ASSERT_NE(decl.type, nullptr);
|
||||||
|
@ -37,43 +37,35 @@ TEST_F(ParserImplTest, VariableIdentDecl_Parses) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_MissingIdent) {
|
TEST_F(ParserImplTest, VariableIdentDecl_MissingIdent) {
|
||||||
auto* p = parser(": f32");
|
auto* p = parser(": f32");
|
||||||
auto decl = p->variable_ident_decl();
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(decl.name, "");
|
ASSERT_EQ(p->error(), "1:1: expected identifier for test");
|
||||||
ASSERT_EQ(decl.type, nullptr);
|
|
||||||
|
|
||||||
auto t = p->next();
|
|
||||||
ASSERT_TRUE(t.IsColon());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_MissingColon) {
|
TEST_F(ParserImplTest, VariableIdentDecl_MissingColon) {
|
||||||
auto* p = parser("my_var f32");
|
auto* p = parser("my_var f32");
|
||||||
auto r = p->variable_ident_decl();
|
auto r = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:8: missing : for identifier declaration");
|
ASSERT_EQ(p->error(), "1:8: expected ':' for test");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_MissingType) {
|
TEST_F(ParserImplTest, VariableIdentDecl_MissingType) {
|
||||||
auto* p = parser("my_var :");
|
auto* p = parser("my_var :");
|
||||||
auto r = p->variable_ident_decl();
|
auto r = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:9: invalid type for identifier declaration");
|
ASSERT_EQ(p->error(), "1:9: invalid type for test");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_InvalidIdent) {
|
TEST_F(ParserImplTest, VariableIdentDecl_InvalidIdent) {
|
||||||
auto* p = parser("123 : f32");
|
auto* p = parser("123 : f32");
|
||||||
auto decl = p->variable_ident_decl();
|
auto decl = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_FALSE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(decl.name, "");
|
ASSERT_EQ(p->error(), "1:1: expected identifier for test");
|
||||||
ASSERT_EQ(decl.type, nullptr);
|
|
||||||
|
|
||||||
auto t = p->next();
|
|
||||||
ASSERT_TRUE(t.IsSintLiteral());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableIdentDecl_InvalidType) {
|
TEST_F(ParserImplTest, VariableIdentDecl_InvalidType) {
|
||||||
auto* p = parser("my_var : invalid");
|
auto* p = parser("my_var : invalid");
|
||||||
auto r = p->variable_ident_decl();
|
auto r = p->expect_variable_ident_decl("test");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(p->error(), "1:10: unknown constructed type 'invalid'");
|
ASSERT_EQ(p->error(), "1:10: unknown constructed type 'invalid'");
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ TEST_F(ParserImplTest, VariableStmt_Const_MissingEqual) {
|
||||||
auto e = p->variable_stmt();
|
auto e = p->variable_stmt();
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_EQ(e, nullptr);
|
ASSERT_EQ(e, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:15: missing = for constant declaration");
|
EXPECT_EQ(p->error(), "1:15: expected '=' for constant declaration");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, VariableStmt_Const_MissingConstructor) {
|
TEST_F(ParserImplTest, VariableStmt_Const_MissingConstructor) {
|
||||||
|
|
Loading…
Reference in New Issue