wsgl parser: Add expect_block(), use it
`expect_block()` takes a start and end token, along with a function to parse a lexical block body.
This reduces code, keeps error messages consistent, and also gives us a future place to try resynchronising the parser so we can have more than one error emitted.
`expect_paren_block()` and `expect_brace_block()` are convenience helpers for providing the start and end tokens for common block types.
Bug: tint:282
Change-Id: I432a0301727b131a6fce875687b952dfc6889a4b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31736
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 248d78c..ec4fc39 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -435,62 +435,38 @@
Source source;
if (match(Token::Type::kLocation, &source)) {
const char* use = "location decoration";
-
- if (!expect(use, Token::Type::kParenLeft))
- return nullptr;
-
- uint32_t val;
- if (!expect_positive_sint(use, &val))
- return nullptr;
-
- if (!expect(use, Token::Type::kParenRight))
- return nullptr;
-
- return std::make_unique<ast::LocationDecoration>(val, source);
+ return expect_paren_block(use, [&] {
+ uint32_t val;
+ bool ok = expect_positive_sint(use, &val);
+ return ok ? std::make_unique<ast::LocationDecoration>(val, source)
+ : nullptr;
+ });
}
if (match(Token::Type::kBuiltin, &source)) {
- if (!expect("builtin decoration", Token::Type::kParenLeft))
- return nullptr;
-
- ast::Builtin builtin;
- std::tie(builtin, source) = expect_builtin();
- if (builtin == ast::Builtin::kNone)
- return nullptr;
-
- if (!expect("builtin decoration", Token::Type::kParenRight))
- return nullptr;
-
- return std::make_unique<ast::BuiltinDecoration>(builtin, source);
+ return expect_paren_block("builtin decoration", [&] {
+ ast::Builtin builtin;
+ std::tie(builtin, source) = expect_builtin();
+ return (builtin != ast::Builtin::kNone)
+ ? std::make_unique<ast::BuiltinDecoration>(builtin, source)
+ : nullptr;
+ });
}
if (match(Token::Type::kBinding, &source)) {
const char* use = "binding decoration";
-
- if (!expect(use, Token::Type::kParenLeft))
- return nullptr;
-
- uint32_t val;
- if (!expect_positive_sint(use, &val))
- return nullptr;
-
- if (!expect(use, Token::Type::kParenRight))
- return nullptr;
-
- return std::make_unique<ast::BindingDecoration>(val, source);
+ return expect_paren_block(use, [&] {
+ uint32_t val;
+ bool ok = expect_positive_sint(use, &val);
+ return ok ? std::make_unique<ast::BindingDecoration>(val, source)
+ : nullptr;
+ });
}
if (match(Token::Type::kSet, &source)) {
const char* use = "set decoration";
-
- if (!expect(use, Token::Type::kParenLeft))
- return nullptr;
-
- uint32_t val;
- if (!expect_positive_sint(use, &val))
- return nullptr;
-
- if (!expect(use, Token::Type::kParenRight))
- return nullptr;
-
- return std::make_unique<ast::SetDecoration>(val, source);
+ return expect_paren_block(use, [&] {
+ uint32_t val;
+ bool ok = expect_positive_sint(use, &val);
+ return ok ? std::make_unique<ast::SetDecoration>(val, source) : nullptr;
+ });
}
return nullptr;
@@ -1200,25 +1176,24 @@
for (;;) {
Source source;
- if (!match(Token::Type::kStride, &source)) {
+ if (match(Token::Type::kStride, &source)) {
+ const char* use = "stride decoration";
+ auto deco = expect_paren_block(use, [&] {
+ uint32_t val;
+ bool ok = expect_nonzero_positive_sint(use, &val);
+ return ok ? std::make_unique<ast::StrideDecoration>(val, source)
+ : nullptr;
+ });
+
+ if (!deco)
+ return false;
+
+ decos.emplace_back(std::move(deco));
+ } else {
add_error(source, "unknown array decoration");
return false;
}
- const char* use = "stride decoration";
-
- if (!expect(use, Token::Type::kParenLeft))
- return false;
-
- uint32_t stride;
- if (!expect_nonzero_positive_sint(use, &stride))
- return false;
-
- decos.push_back(std::make_unique<ast::StrideDecoration>(stride, source));
-
- if (!expect(use, Token::Type::kParenRight))
- return false;
-
if (!match(Token::Type::kComma))
break;
}
@@ -1402,43 +1377,23 @@
// struct_body_decl
// : BRACKET_LEFT struct_member* BRACKET_RIGHT
ast::StructMemberList ParserImpl::struct_body_decl() {
- auto t = peek();
- if (!t.IsBraceLeft()) {
- add_error(t, "missing { for struct declaration");
- return {};
- }
- next(); // Consume the peek
+ return expect_brace_block("struct declaration", [&] {
+ ast::StructMemberList members;
- t = peek();
- if (t.IsBraceRight()) {
- next(); // Consume the peek
- return {};
- }
+ while (!peek().IsBraceRight() && !peek().IsEof()) {
+ auto mem = struct_member();
+ if (has_error())
+ return ast::StructMemberList{};
+ if (mem == nullptr) {
+ add_error(peek(), "invalid struct member");
+ return ast::StructMemberList{};
+ }
- ast::StructMemberList members;
- for (;;) {
- auto mem = struct_member();
- if (has_error())
- return {};
- if (mem == nullptr) {
- add_error(peek(), "invalid struct member");
- return {};
+ members.push_back(std::move(mem));
}
- members.push_back(std::move(mem));
-
- t = peek();
- if (t.IsBraceRight() || t.IsEof())
- break;
- }
-
- t = next();
- if (!t.IsBraceRight()) {
- add_error(t, "missing } for struct declaration");
- return {};
- }
-
- return members;
+ return members;
+ });
}
// struct_member
@@ -1519,18 +1474,12 @@
return nullptr;
const char* use = "offset decoration";
-
- if (!expect(use, Token::Type::kParenLeft))
- return nullptr;
-
- uint32_t val;
- if (!expect_positive_sint(use, &val))
- return nullptr;
-
- if (!expect(use, Token::Type::kParenRight))
- return nullptr;
-
- return std::make_unique<ast::StructMemberOffsetDecoration>(val, source);
+ return expect_paren_block(use, [&] {
+ uint32_t val;
+ bool ok = expect_positive_sint(use, &val);
+ return ok ? std::make_unique<ast::StructMemberOffsetDecoration>(val, source)
+ : nullptr;
+ });
}
// function_decl
@@ -1624,55 +1573,36 @@
// | WORKGROUP_SIZE PAREN_LEFT INT_LITERAL
// (COMMA INT_LITERAL (COMMA INT_LITERAL)?)? PAREN_RIGHT
std::unique_ptr<ast::FunctionDecoration> ParserImpl::function_decoration() {
- auto t = peek();
- auto source = t.source();
- if (t.IsWorkgroupSize()) {
- next(); // Consume the peek
-
- const char* use = "workgroup_size decoration";
-
- if (!expect(use, Token::Type::kParenLeft))
- return nullptr;
-
- uint32_t x;
- if (!expect_nonzero_positive_sint("workgroup_size x parameter", &x)) {
- return nullptr;
- }
-
- uint32_t y = 1;
- uint32_t z = 1;
- if (match(Token::Type::kComma)) {
- if (!expect_nonzero_positive_sint("workgroup_size y parameter", &y)) {
- return nullptr;
+ Source source;
+ if (match(Token::Type::kWorkgroupSize, &source)) {
+ return expect_paren_block("workgroup_size decoration", [&]() {
+ uint32_t x;
+ if (!expect_nonzero_positive_sint("workgroup_size x parameter", &x)) {
+ return std::unique_ptr<ast::WorkgroupDecoration>(nullptr);
}
+ uint32_t y = 1;
+ uint32_t z = 1;
if (match(Token::Type::kComma)) {
- if (!expect_nonzero_positive_sint("workgroup_size z parameter", &z)) {
- return nullptr;
+ if (!expect_nonzero_positive_sint("workgroup_size y parameter", &y)) {
+ return std::unique_ptr<ast::WorkgroupDecoration>(nullptr);
+ }
+ if (match(Token::Type::kComma)) {
+ if (!expect_nonzero_positive_sint("workgroup_size z parameter", &z)) {
+ return std::unique_ptr<ast::WorkgroupDecoration>(nullptr);
+ }
}
}
- }
-
- if (!expect(use, Token::Type::kParenRight))
- return nullptr;
-
- return std::make_unique<ast::WorkgroupDecoration>(uint32_t(x), uint32_t(y),
- uint32_t(z), source);
+ return std::make_unique<ast::WorkgroupDecoration>(x, y, z, source);
+ });
}
- if (t.IsStage()) {
- next(); // Consume the peek
-
- if (!expect("stage decoration", Token::Type::kParenLeft))
- return nullptr;
-
- ast::PipelineStage stage;
- std::tie(stage, source) = expect_pipeline_stage();
- if (stage == ast::PipelineStage::kNone)
- return nullptr;
-
- if (!expect("stage decoration", Token::Type::kParenRight))
- return nullptr;
-
- return std::make_unique<ast::StageDecoration>(stage, source);
+ if (match(Token::Type::kStage, &source)) {
+ return expect_paren_block("stage decoration", [&]() {
+ ast::PipelineStage stage;
+ std::tie(stage, source) = expect_pipeline_stage();
+ return (stage != ast::PipelineStage::kNone)
+ ? std::make_unique<ast::StageDecoration>(stage, source)
+ : nullptr;
+ });
}
return nullptr;
}
@@ -1702,16 +1632,11 @@
if (!expect_ident(use, &name))
return nullptr;
- if (!expect(use, Token::Type::kParenLeft))
- return nullptr;
+ auto params = expect_paren_block(use, [&] { return param_list(); });
- auto params = param_list();
if (has_error())
return nullptr;
- if (!expect(use, Token::Type::kParenRight))
- return nullptr;
-
auto t = next();
if (!t.IsArrow()) {
add_error(t, "missing -> for function declaration");
@@ -1808,45 +1733,23 @@
// body_stmt
// : BRACKET_LEFT statements BRACKET_RIGHT
std::unique_ptr<ast::BlockStatement> ParserImpl::body_stmt() {
- auto t = peek();
- if (!t.IsBraceLeft()) {
- add_error(t, "missing {");
- return nullptr;
- }
-
- next(); // Consume the peek
-
- auto stmts = statements();
- if (has_error())
- return nullptr;
-
- t = next();
- if (!t.IsBraceRight()) {
- add_error(t, "missing }");
- return nullptr;
- }
-
- return stmts;
+ return expect_brace_block("", [&] { return statements(); });
}
// paren_rhs_stmt
// : PAREN_LEFT logical_or_expression PAREN_RIGHT
std::unique_ptr<ast::Expression> ParserImpl::paren_rhs_stmt() {
- if (!expect("", Token::Type::kParenLeft))
- return nullptr;
+ return expect_paren_block("", [&]() -> std::unique_ptr<ast::Expression> {
+ auto expr = logical_or_expression();
+ if (has_error())
+ return nullptr;
- auto expr = logical_or_expression();
- if (has_error())
- return nullptr;
- if (expr == nullptr) {
- add_error(peek(), "unable to parse expression");
- return nullptr;
- }
-
- if (!expect("", Token::Type::kParenRight))
- return nullptr;
-
- return expr;
+ if (expr == nullptr) {
+ add_error(peek(), "unable to parse expression");
+ return nullptr;
+ }
+ return expr;
+ });
}
// statements
@@ -2174,28 +2077,23 @@
return nullptr;
}
- auto t = next();
- if (!t.IsBraceLeft()) {
- add_error(t, "missing { for switch statement");
- return nullptr;
- }
-
ast::CaseStatementList body;
- for (;;) {
- auto stmt = switch_body();
- if (has_error())
- return nullptr;
- if (stmt == nullptr)
- break;
+ bool ok = expect_brace_block("switch statement", [&] {
+ for (;;) {
+ auto stmt = switch_body();
+ if (has_error())
+ return false;
+ if (stmt == nullptr)
+ break;
- body.push_back(std::move(stmt));
- }
+ body.push_back(std::move(stmt));
+ }
+ return true;
+ });
- t = next();
- if (!t.IsBraceRight()) {
- add_error(t, "missing } for switch statement");
+ if (!ok)
return nullptr;
- }
+
return std::make_unique<ast::SwitchStatement>(source, std::move(condition),
std::move(body));
}
@@ -2224,30 +2122,18 @@
stmt->set_selectors(std::move(selectors));
}
- t = next();
- if (!t.IsColon()) {
- add_error(t, "missing : for case statement");
- return nullptr;
- }
+ const char* use = "case statement";
- t = next();
- if (!t.IsBraceLeft()) {
- add_error(t, "missing { for case statement");
+ if (!expect(use, Token::Type::kColon))
return nullptr;
- }
- auto body = case_body();
- if (has_error())
+ auto body = expect_brace_block(use, [&] { return case_body(); });
+
+ if (body == nullptr)
return nullptr;
stmt->set_body(std::move(body));
- t = next();
- if (!t.IsBraceRight()) {
- add_error(t, "missing } for case statement");
- return nullptr;
- }
-
return stmt;
}
@@ -2313,28 +2199,19 @@
if (!match(Token::Type::kLoop, &source))
return nullptr;
- auto t = next();
- if (!t.IsBraceLeft()) {
- add_error(t, "missing { for loop");
- return nullptr;
- }
+ return expect_brace_block(
+ "loop", [&]() -> std::unique_ptr<ast::LoopStatement> {
+ auto body = statements();
+ if (has_error())
+ return nullptr;
- auto body = statements();
- if (has_error())
- return nullptr;
+ auto continuing = continuing_stmt();
+ if (has_error())
+ return nullptr;
- auto continuing = continuing_stmt();
- if (has_error())
- return nullptr;
-
- t = next();
- if (!t.IsBraceRight()) {
- add_error(t, "missing } for loop");
- return nullptr;
- }
-
- return std::make_unique<ast::LoopStatement>(source, std::move(body),
- std::move(continuing));
+ return std::make_unique<ast::LoopStatement>(source, std::move(body),
+ std::move(continuing));
+ });
}
ForHeader::ForHeader(std::unique_ptr<ast::Statement> init,
@@ -2408,32 +2285,15 @@
if (!match(Token::Type::kFor, &source))
return nullptr;
- if (!expect("for loop", Token::Type::kParenLeft))
+ auto header = expect_paren_block("for loop", [&] { return for_header(); });
+ if (header == nullptr)
return nullptr;
- auto header = for_header();
- if (has_error())
- return nullptr;
+ auto body = expect_brace_block("for loop", [&] { return statements(); });
- if (!expect("for loop", Token::Type::kParenRight))
+ if (body == nullptr)
return nullptr;
- auto t = next();
- if (!t.IsBraceLeft()) {
- add_error(t, "missing for loop {");
- return nullptr;
- }
-
- auto body = statements();
- if (has_error())
- return nullptr;
-
- t = next();
- if (!t.IsBraceRight()) {
- add_error(t, "missing for loop }");
- return nullptr;
- }
-
// The for statement is a syntactic sugar on top of the loop statement.
// We create corresponding nodes in ast with the exact same behaviour
// as we would expect from the loop statement.
@@ -2609,19 +2469,21 @@
if (has_error())
return nullptr;
if (type != nullptr) {
- if (!expect("type constructor", Token::Type::kParenLeft))
- return nullptr;
-
- t = peek();
ast::ExpressionList params;
- if (!t.IsParenRight() && !t.IsEof()) {
- params = argument_expression_list();
- if (has_error())
- return nullptr;
- }
- if (!expect("type constructor", Token::Type::kParenRight))
+ auto ok = expect_paren_block("type constructor", [&] {
+ t = peek();
+ if (!t.IsParenRight() && !t.IsEof()) {
+ params = argument_expression_list();
+ if (has_error())
+ return false;
+ }
+ return true;
+ });
+
+ if (!ok) {
return nullptr;
+ }
return std::make_unique<ast::TypeConstructorExpression>(source, type,
std::move(params));
@@ -3271,36 +3133,30 @@
auto* type = type_decl();
if (type != nullptr) {
- if (!expect("type constructor", Token::Type::kParenLeft))
- return nullptr;
-
ast::ExpressionList params;
- auto param = const_expr_internal(depth + 1);
- if (has_error())
- return nullptr;
- if (param == nullptr) {
- add_error(peek(), "unable to parse constant expression");
- return nullptr;
- }
- params.push_back(std::move(param));
- for (;;) {
- t = peek();
- if (!t.IsComma())
- break;
-
- next(); // Consume the peek
-
- param = const_expr_internal(depth + 1);
+ bool ok = expect_paren_block("type constructor", [&] {
+ auto param = const_expr_internal(depth + 1);
if (has_error())
- return nullptr;
+ return false;
if (param == nullptr) {
add_error(peek(), "unable to parse constant expression");
- return nullptr;
+ return false;
}
params.push_back(std::move(param));
- }
+ while (match(Token::Type::kComma)) {
+ param = const_expr_internal(depth + 1);
+ if (has_error())
+ return false;
+ if (param == nullptr) {
+ add_error(peek(), "unable to parse constant expression");
+ return false;
+ }
+ params.push_back(std::move(param));
+ }
+ return true;
+ });
- if (!expect("type constructor", Token::Type::kParenRight))
+ if (!ok)
return nullptr;
return std::make_unique<ast::TypeConstructorExpression>(source, type,
@@ -3401,6 +3257,36 @@
return true;
}
+template <typename F, typename T>
+T ParserImpl::expect_block(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_paren_block(const std::string& use, F&& body) {
+ return expect_block(Token::Type::kParenLeft, Token::Type::kParenRight, use,
+ std::forward<F>(body));
+}
+
+template <typename F, typename T>
+T ParserImpl::expect_brace_block(const std::string& use, F&& body) {
+ return expect_block(Token::Type::kBraceLeft, Token::Type::kBraceRight, use,
+ std::forward<F>(body));
+}
+
} // namespace wgsl
} // namespace reader
} // namespace tint
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 91c54fa..e1de67f 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -18,6 +18,7 @@
#include <deque>
#include <memory>
#include <string>
+#include <type_traits>
#include <unordered_map>
#include <utility>
@@ -435,6 +436,10 @@
std::unique_ptr<ast::AssignmentStatement> assignment_stmt();
private:
+ /// ResultType resolves to the return type for the function or lambda F.
+ template <typename F>
+ using ResultType = typename std::result_of<F()>::type;
+
/// @returns true and consumes the next token if it equals |tok|.
/// @param source if not nullptr, the next token's source is written to this
/// pointer, regardless of success or error
@@ -476,6 +481,45 @@
bool expect_ident(const std::string& use,
std::string* out,
Source* source = nullptr);
+ /// Parses a lexical block starting with the token |start| and ending with
+ /// the token |end|. |body| is called to parse the lexical block body between
+ /// the |start| and |end| tokens.
+ /// If the |start| or |end| tokens are not matched then an error is generated
+ /// and a zero-initialized |T| is returned.
+ /// If |body| raises an error while parsing then a zero-initialized |T| is
+ /// returned.
+ /// @param start the token that begins the lexical block
+ /// @param end the token that ends the lexical block
+ /// @param use a description of what was being parsed if an error was raised
+ /// @param body a function or lambda that is called to parse the lexical block
+ /// body, with the signature T().
+ /// @return the value returned by |body| if no errors are raised, otherwise
+ /// a zero-initialized |T|.
+ template <typename F, typename T = ResultType<F>>
+ T expect_block(Token::Type start,
+ Token::Type end,
+ const std::string& use,
+ F&& body);
+ /// A convenience function that calls |expect_block| passing
+ /// |Token::Type::kParenLeft| and |Token::Type::kParenRight| for the |start|
+ /// and |end| arguments, respectively.
+ /// @param use a description of what was being parsed if an error was raised
+ /// @param body a function or lambda that is called to parse the lexical block
+ /// body, with the signature T().
+ /// @return the value returned by |body| if no errors are raised, otherwise
+ /// a zero-initialized |T|.
+ template <typename F, typename T = ResultType<F>>
+ T expect_paren_block(const std::string& use, F&& body);
+ /// A convenience function that calls |expect_block| passing
+ /// |Token::Type::kBraceLeft| and |Token::Type::kBraceRight| for the |start|
+ /// and |end| arguments, respectively.
+ /// @param use a description of what was being parsed if an error was raised
+ /// @param body a function or lambda that is called to parse the lexical block
+ /// body, with the signature T().
+ /// @return the value returned by |body| if no errors are raised, otherwise
+ /// a zero-initialized |T|.
+ template <typename F, typename T = ResultType<F>>
+ T expect_brace_block(const std::string& use, F&& body);
ast::type::Type* type_decl_pointer(Token t);
ast::type::Type* type_decl_vector(Token t);
diff --git a/src/reader/wgsl/parser_impl_body_stmt_test.cc b/src/reader/wgsl/parser_impl_body_stmt_test.cc
index 1bd1fbe..e578651 100644
--- a/src/reader/wgsl/parser_impl_body_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_body_stmt_test.cc
@@ -44,14 +44,14 @@
auto* p = parser("{fn main() -> void {}}");
auto e = p->body_stmt();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:2: missing }");
+ EXPECT_EQ(p->error(), "1:2: expected '}'");
}
TEST_F(ParserImplTest, BodyStmt_MissingRightParen) {
auto* p = parser("{return;");
auto e = p->body_stmt();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:9: missing }");
+ EXPECT_EQ(p->error(), "1:9: expected '}'");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_else_stmt_test.cc b/src/reader/wgsl/parser_impl_else_stmt_test.cc
index fa5af49..f83fa4a 100644
--- a/src/reader/wgsl/parser_impl_else_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_else_stmt_test.cc
@@ -37,7 +37,7 @@
auto e = p->else_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:8: missing }");
+ EXPECT_EQ(p->error(), "1:8: expected '}'");
}
TEST_F(ParserImplTest, ElseStmt_MissingBody) {
@@ -45,7 +45,7 @@
auto e = p->else_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:5: missing {");
+ EXPECT_EQ(p->error(), "1:5: expected '{'");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
index 13aff03..93ce334 100644
--- a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
@@ -55,14 +55,14 @@
auto* p = parser("elseif (true) { fn main() -> void {}}");
auto e = p->elseif_stmt();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:17: missing }");
+ 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_EQ(p->error(), "1:14: missing {");
+ EXPECT_EQ(p->error(), "1:14: expected '{'");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_error_msg_test.cc b/src/reader/wgsl/parser_impl_error_msg_test.cc
index dac8e45..899a6af 100644
--- a/src/reader/wgsl/parser_impl_error_msg_test.cc
+++ b/src/reader/wgsl/parser_impl_error_msg_test.cc
@@ -239,14 +239,14 @@
TEST_F(ParserImplErrorTest, ForLoopMissingLBrace) {
EXPECT("fn f() -> void { for (var i : i32 = 0; i < 8; i=i+1) } }",
- "test.wgsl:1:54 error: missing for loop {\n"
+ "test.wgsl:1:54 error: expected '{' for for loop\n"
"fn f() -> void { for (var i : i32 = 0; i < 8; i=i+1) } }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, ForLoopMissingRBrace) {
EXPECT("fn f() -> void { for (var i : i32 = 0; i < 8; i=i+1) {",
- "test.wgsl:1:55 error: missing for loop }\n"
+ "test.wgsl:1:55 error: expected '}' for for loop\n"
"fn f() -> void { for (var i : i32 = 0; i < 8; i=i+1) {\n"
" ^\n");
}
@@ -438,14 +438,14 @@
TEST_F(ParserImplErrorTest, FunctionDeclMissingLBrace) {
EXPECT("fn f() -> void }",
- "test.wgsl:1:16 error: missing {\n"
+ "test.wgsl:1:16 error: expected '{'\n"
"fn f() -> void }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, FunctionDeclMissingRBrace) {
EXPECT("fn f() -> void {",
- "test.wgsl:1:17 error: missing }\n"
+ "test.wgsl:1:17 error: expected '}'\n"
"fn f() -> void {\n"
" ^\n");
}
@@ -647,14 +647,14 @@
TEST_F(ParserImplErrorTest, GlobalDeclStructDeclMissingLBrace) {
EXPECT("struct S };",
- "test.wgsl:1:10 error: missing { for struct declaration\n"
+ "test.wgsl:1:10 error: expected '{' for struct declaration\n"
"struct S };\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, GlobalDeclStructDeclMissingRBrace) {
EXPECT("struct S { i : i32;",
- "test.wgsl:1:20 error: missing } for struct declaration\n"
+ "test.wgsl:1:20 error: expected '}' for struct declaration\n"
"struct S { i : i32;\n"
" ^\n");
}
@@ -1101,14 +1101,14 @@
TEST_F(ParserImplErrorTest, LoopMissingLBrace) {
EXPECT("fn f() -> void { loop } }",
- "test.wgsl:1:23 error: missing { for loop\n"
+ "test.wgsl:1:23 error: expected '{' for loop\n"
"fn f() -> void { loop } }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, LoopMissingRBrace) {
EXPECT("fn f() -> void { loop {",
- "test.wgsl:1:24 error: missing } for loop\n"
+ "test.wgsl:1:24 error: expected '}' for loop\n"
"fn f() -> void { loop {\n"
" ^\n");
}
@@ -1157,14 +1157,14 @@
TEST_F(ParserImplErrorTest, SwitchStmtMissingLBrace) {
EXPECT("fn f() -> void { switch(1) }",
- "test.wgsl:1:28 error: missing { for switch statement\n"
+ "test.wgsl:1:28 error: expected '{' for switch statement\n"
"fn f() -> void { switch(1) }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, SwitchStmtMissingRBrace) {
EXPECT("fn f() -> void { switch(1) {",
- "test.wgsl:1:29 error: missing } for switch statement\n"
+ "test.wgsl:1:29 error: expected '}' for switch statement\n"
"fn f() -> void { switch(1) {\n"
" ^\n");
}
@@ -1186,21 +1186,21 @@
TEST_F(ParserImplErrorTest, SwitchStmtCaseMissingColon) {
EXPECT("fn f() -> void { switch(1) { case 1 {} } }",
- "test.wgsl:1:37 error: missing : for case statement\n"
+ "test.wgsl:1:37 error: expected ':' for case statement\n"
"fn f() -> void { switch(1) { case 1 {} } }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, SwitchStmtCaseMissingLBrace) {
EXPECT("fn f() -> void { switch(1) { case 1: } } }",
- "test.wgsl:1:38 error: missing { for case statement\n"
+ "test.wgsl:1:38 error: expected '{' for case statement\n"
"fn f() -> void { switch(1) { case 1: } } }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, SwitchStmtCaseMissingRBrace) {
EXPECT("fn f() -> void { switch(1) { case 1: {",
- "test.wgsl:1:39 error: missing } for case statement\n"
+ "test.wgsl:1:39 error: expected '}' for case statement\n"
"fn f() -> void { switch(1) { case 1: {\n"
" ^\n");
}
diff --git a/src/reader/wgsl/parser_impl_for_stmt_test.cc b/src/reader/wgsl/parser_impl_for_stmt_test.cc
index 6fffc65..b599e65 100644
--- a/src/reader/wgsl/parser_impl_for_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_for_stmt_test.cc
@@ -200,7 +200,7 @@
// Test a for loop with missing left brace is invalid.
TEST_F(ForStmtErrorTest, MissingLeftBrace) {
std::string for_str = "for (;;)";
- std::string error_str = "1:9: missing for loop {";
+ std::string error_str = "1:9: expected '{' for for loop";
TestForWithError(for_str, error_str);
}
@@ -208,7 +208,7 @@
// Test a for loop with missing right brace is invalid.
TEST_F(ForStmtErrorTest, MissingRightBrace) {
std::string for_str = "for (;;) {";
- std::string error_str = "1:11: missing for loop }";
+ std::string error_str = "1:11: expected '}' for for loop";
TestForWithError(for_str, error_str);
}
@@ -275,7 +275,7 @@
// Test a for loop with a body not matching statements
TEST_F(ForStmtErrorTest, InvalidBodyMatch) {
std::string for_str = "for (;;) { fn main() -> void {} }";
- std::string error_str = "1:12: missing for loop }";
+ std::string error_str = "1:12: expected '}' for for loop";
TestForWithError(for_str, 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 79720a1..549273a 100644
--- a/src/reader/wgsl/parser_impl_function_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_function_decl_test.cc
@@ -174,7 +174,7 @@
auto f = p->function_decl();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(f, nullptr);
- EXPECT_EQ(p->error(), "1:19: missing {");
+ EXPECT_EQ(p->error(), "1:19: expected '{'");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_if_stmt_test.cc b/src/reader/wgsl/parser_impl_if_stmt_test.cc
index 63cba71..50c3827 100644
--- a/src/reader/wgsl/parser_impl_if_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_if_stmt_test.cc
@@ -78,7 +78,7 @@
auto e = p->if_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:10: missing }");
+ EXPECT_EQ(p->error(), "1:10: expected '}'");
}
TEST_F(ParserImplTest, IfStmt_MissingBody) {
@@ -86,7 +86,7 @@
auto e = p->if_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:7: missing {");
+ EXPECT_EQ(p->error(), "1:7: expected '{'");
}
TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
@@ -94,7 +94,7 @@
auto e = p->if_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:24: missing }");
+ EXPECT_EQ(p->error(), "1:24: expected '}'");
}
TEST_F(ParserImplTest, IfStmt_InvalidElse) {
@@ -102,7 +102,7 @@
auto e = p->if_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:18: missing }");
+ EXPECT_EQ(p->error(), "1:18: expected '}'");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_loop_stmt_test.cc b/src/reader/wgsl/parser_impl_loop_stmt_test.cc
index 71962dd..41aea2f 100644
--- a/src/reader/wgsl/parser_impl_loop_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_loop_stmt_test.cc
@@ -70,7 +70,7 @@
auto e = p->loop_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:6: missing { for loop");
+ EXPECT_EQ(p->error(), "1:6: expected '{' for loop");
}
TEST_F(ParserImplTest, LoopStmt_MissingBracketRight) {
@@ -78,7 +78,7 @@
auto e = p->loop_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:17: missing } for loop");
+ EXPECT_EQ(p->error(), "1:17: expected '}' for loop");
}
TEST_F(ParserImplTest, LoopStmt_InvalidStatements) {
diff --git a/src/reader/wgsl/parser_impl_statement_test.cc b/src/reader/wgsl/parser_impl_statement_test.cc
index ee6df75..2cebedf 100644
--- a/src/reader/wgsl/parser_impl_statement_test.cc
+++ b/src/reader/wgsl/parser_impl_statement_test.cc
@@ -90,7 +90,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:10: missing }");
+ EXPECT_EQ(p->error(), "1:10: expected '}'");
}
TEST_F(ParserImplTest, Statement_Variable) {
@@ -146,7 +146,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:6: missing { for loop");
+ EXPECT_EQ(p->error(), "1:6: expected '{' for loop");
}
TEST_F(ParserImplTest, Statement_Assignment) {
@@ -235,7 +235,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:3: missing }");
+ EXPECT_EQ(p->error(), "1:3: expected '}'");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_struct_body_decl_test.cc b/src/reader/wgsl/parser_impl_struct_body_decl_test.cc
index 38e8c75..33c4b4f 100644
--- a/src/reader/wgsl/parser_impl_struct_body_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_body_decl_test.cc
@@ -59,7 +59,7 @@
auto* p = parser("{a : i32;");
auto m = p->struct_body_decl();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:10: missing } for struct declaration");
+ EXPECT_EQ(p->error(), "1:10: expected '}' for struct declaration");
}
TEST_F(ParserImplTest, StructBodyDecl_InvalidToken) {
diff --git a/src/reader/wgsl/parser_impl_struct_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decl_test.cc
index 884fea8..ebf1c4a 100644
--- a/src/reader/wgsl/parser_impl_struct_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decl_test.cc
@@ -94,7 +94,7 @@
auto s = p->struct_decl();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(s, nullptr);
- EXPECT_EQ(p->error(), "1:10: missing { for struct declaration");
+ EXPECT_EQ(p->error(), "1:10: expected '{' for struct declaration");
}
TEST_F(ParserImplTest, StructDecl_InvalidStructBody) {
diff --git a/src/reader/wgsl/parser_impl_switch_body_test.cc b/src/reader/wgsl/parser_impl_switch_body_test.cc
index b5d3cd1..6b4078c 100644
--- a/src/reader/wgsl/parser_impl_switch_body_test.cc
+++ b/src/reader/wgsl/parser_impl_switch_body_test.cc
@@ -62,7 +62,7 @@
auto e = p->switch_body();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:8: missing : for case statement");
+ EXPECT_EQ(p->error(), "1:8: expected ':' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketLeft) {
@@ -70,7 +70,7 @@
auto e = p->switch_body();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:9: missing { for case statement");
+ EXPECT_EQ(p->error(), "1:9: expected '{' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Case_MissingBracketRight) {
@@ -78,7 +78,7 @@
auto e = p->switch_body();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:18: missing } for case statement");
+ EXPECT_EQ(p->error(), "1:18: expected '}' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Case_InvalidCaseBody) {
@@ -86,7 +86,7 @@
auto e = p->switch_body();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:11: missing } for case statement");
+ EXPECT_EQ(p->error(), "1:11: expected '}' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Default) {
@@ -105,7 +105,7 @@
auto e = p->switch_body();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:9: missing : for case statement");
+ EXPECT_EQ(p->error(), "1:9: expected ':' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketLeft) {
@@ -113,7 +113,7 @@
auto e = p->switch_body();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:10: missing { for case statement");
+ EXPECT_EQ(p->error(), "1:10: expected '{' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Default_MissingBracketRight) {
@@ -121,7 +121,7 @@
auto e = p->switch_body();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:19: missing } for case statement");
+ EXPECT_EQ(p->error(), "1:19: expected '}' for case statement");
}
TEST_F(ParserImplTest, SwitchBody_Default_InvalidCaseBody) {
@@ -129,7 +129,7 @@
auto e = p->switch_body();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:12: missing } for case statement");
+ EXPECT_EQ(p->error(), "1:12: expected '}' for case statement");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_switch_stmt_test.cc b/src/reader/wgsl/parser_impl_switch_stmt_test.cc
index c3f99d6..15b6a5c 100644
--- a/src/reader/wgsl/parser_impl_switch_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_switch_stmt_test.cc
@@ -84,7 +84,7 @@
auto e = p->switch_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:11: missing { for switch statement");
+ EXPECT_EQ(p->error(), "1:11: expected '{' for switch statement");
}
TEST_F(ParserImplTest, SwitchStmt_MissingBracketRight) {
@@ -92,7 +92,7 @@
auto e = p->switch_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:12: missing } for switch statement");
+ EXPECT_EQ(p->error(), "1:12: expected '}' for switch statement");
}
TEST_F(ParserImplTest, SwitchStmt_InvalidBody) {