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) {