wsgl parser: Use expect() for semicolon checks
Keeps error message consistent. Reduces code.
Bug: tint:282
Change-Id: Ifddb63b65d44427e0680bb25837fcb24ca854eb0
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31725
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index f383dee..84af7b5 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -224,11 +224,9 @@
return;
}
if (gv != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ';' for variable declaration");
+ if (!expect("variable declaration", Token::Type::kSemicolon))
return;
- }
+
module_.AddGlobalVariable(std::move(gv));
return;
}
@@ -238,11 +236,9 @@
return;
}
if (gc != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ';' for constant declaration");
+ if (!expect("constant declaration", Token::Type::kSemicolon))
return;
- }
+
module_.AddGlobalVariable(std::move(gc));
return;
}
@@ -252,11 +248,9 @@
return;
}
if (ta != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ';' for type alias");
+ if (!expect("type alias", Token::Type::kSemicolon))
return;
- }
+
module_.AddConstructedType(ta);
return;
}
@@ -266,11 +260,9 @@
return;
}
if (str != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ';' for struct declaration");
+ if (!expect("struct declaration", Token::Type::kSemicolon))
return;
- }
+
auto* type = ctx_.type_mgr().Get(std::move(str));
register_constructed(type->AsStruct()->name(), type);
module_.AddConstructedType(type);
@@ -1634,11 +1626,8 @@
return nullptr;
}
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ; for struct member");
+ if (!expect("struct member", Token::Type::kSemicolon))
return nullptr;
- }
return std::make_unique<ast::StructMember>(decl.source, decl.name, decl.type,
std::move(decos));
@@ -2115,21 +2104,18 @@
// | assignment_stmt SEMICOLON
// | body_stmt?
std::unique_ptr<ast::Statement> ParserImpl::statement() {
- auto t = peek();
- if (t.IsSemicolon()) {
- next(); // Consume the peek
- return statement();
+ while (match(Token::Type::kSemicolon)) {
+ // Skip empty statements
}
+ auto t = peek();
auto ret_stmt = return_stmt();
if (has_error())
return nullptr;
if (ret_stmt != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ;");
+ if (!expect("return statement", Token::Type::kSemicolon))
return nullptr;
- }
+
return ret_stmt;
}
@@ -2161,11 +2147,9 @@
if (has_error())
return nullptr;
if (func != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ;");
+ if (!expect("function call", Token::Type::kSemicolon))
return nullptr;
- }
+
return func;
}
@@ -2173,11 +2157,9 @@
if (has_error())
return nullptr;
if (var != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ;");
+ if (!expect("variable declaration", Token::Type::kSemicolon))
return nullptr;
- }
+
return var;
}
@@ -2185,11 +2167,9 @@
if (has_error())
return nullptr;
if (b != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ;");
+ if (!expect("break statement", Token::Type::kSemicolon))
return nullptr;
- }
+
return b;
}
@@ -2197,11 +2177,9 @@
if (has_error())
return nullptr;
if (cont != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ;");
+ if (!expect("continue statement", Token::Type::kSemicolon))
return nullptr;
- }
+
return cont;
}
@@ -2209,11 +2187,9 @@
auto source = t.source();
next(); // Consume the peek
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ;");
+ if (!expect("discard statement", Token::Type::kSemicolon))
return nullptr;
- }
+
return std::make_unique<ast::DiscardStatement>(source);
}
@@ -2221,11 +2197,9 @@
if (has_error())
return nullptr;
if (assign != nullptr) {
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ;");
+ if (!expect("assignment statement", Token::Type::kSemicolon))
return nullptr;
- }
+
return assign;
}
@@ -2547,11 +2521,8 @@
auto source = t.source();
next(); // Consume the peek
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ;");
- return {};
- }
+ if (!expect("fallthrough statement", Token::Type::kSemicolon))
+ return nullptr;
ret->append(std::make_unique<ast::FallthroughStatement>(source));
break;
@@ -2638,22 +2609,16 @@
}
}
- auto t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ';' after initializer in for loop");
+ if (!expect("initializer in for loop", Token::Type::kSemicolon))
return nullptr;
- }
auto condition = logical_or_expression();
if (has_error()) {
return nullptr;
}
- t = next();
- if (!t.IsSemicolon()) {
- add_error(t, "missing ';' after condition in for loop");
+ if (!expect("condition in for loop", Token::Type::kSemicolon))
return nullptr;
- }
std::unique_ptr<ast::Statement> continuing = nullptr;
if (continuing == nullptr) {
@@ -3634,7 +3599,7 @@
auto t = next();
if (!t.Is(tok)) {
std::stringstream err;
- err << "expected " << Token::TypeToName(tok);
+ err << "expected '" << Token::TypeToName(tok) << "'";
if (!use.empty()) {
err << " for " << use;
}
diff --git a/src/reader/wgsl/parser_impl_call_stmt_test.cc b/src/reader/wgsl/parser_impl_call_stmt_test.cc
index 1b49049..9f567e9 100644
--- a/src/reader/wgsl/parser_impl_call_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_call_stmt_test.cc
@@ -70,7 +70,7 @@
auto* p = parser("a()");
auto e = p->statement();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:4: missing ;");
+ EXPECT_EQ(p->error(), "1:4: expected ';' for function call");
}
TEST_F(ParserImplTest, Statement_Call_Bad_ArgList) {
diff --git a/src/reader/wgsl/parser_impl_case_body_test.cc b/src/reader/wgsl/parser_impl_case_body_test.cc
index 61c6ec0..b878037 100644
--- a/src/reader/wgsl/parser_impl_case_body_test.cc
+++ b/src/reader/wgsl/parser_impl_case_body_test.cc
@@ -60,7 +60,7 @@
auto e = p->case_body();
ASSERT_TRUE(p->has_error());
EXPECT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:12: missing ;");
+ EXPECT_EQ(p->error(), "1:12: expected ';' for fallthrough statement");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_continuing_stmt_test.cc b/src/reader/wgsl/parser_impl_continuing_stmt_test.cc
index c570d84..9f2ab58 100644
--- a/src/reader/wgsl/parser_impl_continuing_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_continuing_stmt_test.cc
@@ -34,7 +34,7 @@
auto e = p->continuing_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:22: missing ;");
+ EXPECT_EQ(p->error(), "1:22: expected ';' for discard statement");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_error_msg_test.cc b/src/reader/wgsl/parser_impl_error_msg_test.cc
index 3f403a4..c73857d 100644
--- a/src/reader/wgsl/parser_impl_error_msg_test.cc
+++ b/src/reader/wgsl/parser_impl_error_msg_test.cc
@@ -77,7 +77,7 @@
TEST_F(ParserImplErrorTest, AssignmentStmtMissingSemicolon) {
EXPECT("fn f() -> void { a = 1 }",
- "test.wgsl:1:24 error: missing ;\n"
+ "test.wgsl:1:24 error: expected ';' for assignment statement\n"
"fn f() -> void { a = 1 }\n"
" ^\n");
}
@@ -112,7 +112,7 @@
TEST_F(ParserImplErrorTest, BreakStmtMissingSemicolon) {
EXPECT("fn f() -> void { loop { break } }",
- "test.wgsl:1:31 error: missing ;\n"
+ "test.wgsl:1:31 error: expected ';' for break statement\n"
"fn f() -> void { loop { break } }\n"
" ^\n");
}
@@ -148,7 +148,7 @@
TEST_F(ParserImplErrorTest, CallStmtMissingSemicolon) {
EXPECT("fn f() -> void { f() }",
- "test.wgsl:1:22 error: missing ;\n"
+ "test.wgsl:1:22 error: expected ';' for function call\n"
"fn f() -> void { f() }\n"
" ^\n");
}
@@ -190,14 +190,14 @@
TEST_F(ParserImplErrorTest, ContinueStmtMissingSemicolon) {
EXPECT("fn f() -> void { loop { continue } }",
- "test.wgsl:1:34 error: missing ;\n"
+ "test.wgsl:1:34 error: expected ';' for continue statement\n"
"fn f() -> void { loop { continue } }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, DiscardStmtMissingSemicolon) {
EXPECT("fn f() -> void { discard }",
- "test.wgsl:1:26 error: missing ;\n"
+ "test.wgsl:1:26 error: expected ';' for discard statement\n"
"fn f() -> void { discard }\n"
" ^\n");
}
@@ -211,14 +211,14 @@
TEST_F(ParserImplErrorTest, ForLoopInitializerMissingSemicolon) {
EXPECT("fn f() -> void { for (var i : i32 = 0 i < 8; i=i+1) {} }",
- "test.wgsl:1:39 error: missing ';' after initializer in for loop\n"
+ "test.wgsl:1:39 error: expected ';' for initializer in for loop\n"
"fn f() -> void { for (var i : i32 = 0 i < 8; i=i+1) {} }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, ForLoopConditionMissingSemicolon) {
EXPECT("fn f() -> void { for (var i : i32 = 0; i < 8 i=i+1) {} }",
- "test.wgsl:1:46 error: missing ';' after condition in for loop\n"
+ "test.wgsl:1:46 error: expected ';' for condition in for loop\n"
"fn f() -> void { for (var i : i32 = 0; i < 8 i=i+1) {} }\n"
" ^\n");
}
@@ -429,7 +429,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclConstMissingSemicolon) {
EXPECT("const i : i32 = 1",
- "test.wgsl:1:18 error: missing ';' for constant declaration\n"
+ "test.wgsl:1:18 error: expected ';' for constant declaration\n"
"const i : i32 = 1\n"
" ^\n");
}
@@ -589,7 +589,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclStructDeclMissingSemicolon) {
EXPECT("struct S {}",
- "test.wgsl:1:12 error: missing ';' for struct declaration\n"
+ "test.wgsl:1:12 error: expected ';' for struct declaration\n"
"struct S {}\n"
" ^\n");
}
@@ -631,7 +631,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclStructMemberMissingSemicolon) {
EXPECT("struct S { i : i32 };",
- "test.wgsl:1:20 error: missing ; for struct member\n"
+ "test.wgsl:1:20 error: expected ';' for struct member\n"
"struct S { i : i32 };\n"
" ^\n");
}
@@ -687,7 +687,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclTypeAliasMissingSemicolon) {
EXPECT("type meow = f32",
- "test.wgsl:1:16 error: missing ';' for type alias\n"
+ "test.wgsl:1:16 error: expected ';' for type alias\n"
"type meow = f32\n"
" ^\n");
}
@@ -932,7 +932,7 @@
TEST_F(ParserImplErrorTest, GlobalDeclVarMissingSemicolon) {
EXPECT("var i : i32",
- "test.wgsl:1:12 error: missing ';' for variable declaration\n"
+ "test.wgsl:1:12 error: expected ';' for variable declaration\n"
"var i : i32\n"
" ^\n");
}
@@ -1086,7 +1086,7 @@
TEST_F(ParserImplErrorTest, ReturnStmtMissingSemicolon) {
EXPECT("fn f() -> void { return }",
- "test.wgsl:1:25 error: missing ;\n"
+ "test.wgsl:1:25 error: expected ';' for return statement\n"
"fn f() -> void { return }\n"
" ^\n");
}
@@ -1150,14 +1150,14 @@
TEST_F(ParserImplErrorTest, SwitchStmtCaseFallthroughMissingSemicolon) {
EXPECT("fn f() -> void { switch(1) { case 1: { fallthrough } case 2: {} } }",
- "test.wgsl:1:52 error: missing ;\n"
+ "test.wgsl:1:52 error: expected ';' for fallthrough statement\n"
"fn f() -> void { switch(1) { case 1: { fallthrough } case 2: {} } }\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, VarStmtMissingSemicolon) {
EXPECT("fn f() -> void { var a : u32 }",
- "test.wgsl:1:30 error: missing ;\n"
+ "test.wgsl:1:30 error: expected ';' for variable declaration\n"
"fn f() -> void { var a : u32 }\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 f0b2435..bbd036b 100644
--- a/src/reader/wgsl/parser_impl_for_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_for_stmt_test.cc
@@ -176,7 +176,7 @@
// Test a for loop with missing first semicolon is invalid.
TEST_F(ForStmtErrorTest, MissingFirstSemicolon) {
std::string for_str = "for () {}";
- std::string error_str = "1:6: missing ';' after initializer in for loop";
+ std::string error_str = "1:6: expected ';' for initializer in for loop";
TestForWithError(for_str, error_str);
}
@@ -184,7 +184,7 @@
// Test a for loop with missing second semicolon is invalid.
TEST_F(ForStmtErrorTest, MissingSecondSemicolon) {
std::string for_str = "for (;) {}";
- std::string error_str = "1:7: missing ';' after condition in for loop";
+ std::string error_str = "1:7: expected ';' for condition in for loop";
TestForWithError(for_str, error_str);
}
@@ -225,7 +225,7 @@
// variable_stmt | assignment_stmt | func_call_stmt.
TEST_F(ForStmtErrorTest, InvalidInitializerMatch) {
std::string for_str = "for (if (true) {} ;;) { }";
- std::string error_str = "1:6: missing ';' after initializer in for loop";
+ std::string error_str = "1:6: expected ';' for initializer in for loop";
TestForWithError(for_str, error_str);
}
@@ -242,7 +242,7 @@
// logical_or_expression.
TEST_F(ForStmtErrorTest, InvalidBreakConditionMatch) {
std::string for_str = "for (; var i: i32 = 0;) { }";
- std::string error_str = "1:8: missing ';' after condition in for loop";
+ std::string error_str = "1:8: expected ';' for condition in 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 00558a7..79720a1 100644
--- a/src/reader/wgsl/parser_impl_function_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_function_decl_test.cc
@@ -166,7 +166,7 @@
auto f = p->function_decl();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(f, nullptr);
- EXPECT_EQ(p->error(), "1:28: missing ;");
+ EXPECT_EQ(p->error(), "1:28: expected ';' for return statement");
}
TEST_F(ParserImplTest, FunctionDecl_MissingLeftBrace) {
diff --git a/src/reader/wgsl/parser_impl_global_decl_test.cc b/src/reader/wgsl/parser_impl_global_decl_test.cc
index cc93b06..fc41e26 100644
--- a/src/reader/wgsl/parser_impl_global_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_decl_test.cc
@@ -52,7 +52,7 @@
auto* p = parser("var<out> a : vec2<i32>");
p->global_decl();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:23: missing ';' for variable declaration");
+ EXPECT_EQ(p->error(), "1:23: expected ';' for variable declaration");
}
TEST_F(ParserImplTest, GlobalDecl_GlobalConstant) {
@@ -78,7 +78,7 @@
auto* p = parser("const a : vec2<i32> = vec2<i32>(1, 2)");
p->global_decl();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:38: missing ';' for constant declaration");
+ EXPECT_EQ(p->error(), "1:38: expected ';' for constant declaration");
}
TEST_F(ParserImplTest, GlobalDecl_TypeAlias) {
@@ -124,7 +124,7 @@
auto* p = parser("type A = i32");
p->global_decl();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:13: missing ';' for type alias");
+ EXPECT_EQ(p->error(), "1:13: expected ';' for type alias");
}
TEST_F(ParserImplTest, GlobalDecl_Function) {
@@ -225,7 +225,7 @@
auto* p = parser("[[block]] struct A {}");
p->global_decl();
ASSERT_TRUE(p->has_error());
- EXPECT_EQ(p->error(), "1:22: missing ';' for struct declaration");
+ EXPECT_EQ(p->error(), "1:22: expected ';' for struct declaration");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_loop_stmt_test.cc b/src/reader/wgsl/parser_impl_loop_stmt_test.cc
index f8cc432..71962dd 100644
--- a/src/reader/wgsl/parser_impl_loop_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_loop_stmt_test.cc
@@ -86,7 +86,7 @@
auto e = p->loop_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:16: missing ;");
+ EXPECT_EQ(p->error(), "1:16: expected ';' for discard statement");
}
TEST_F(ParserImplTest, LoopStmt_InvalidContinuing) {
@@ -94,7 +94,7 @@
auto e = p->loop_stmt();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:29: missing ;");
+ EXPECT_EQ(p->error(), "1:29: expected ';' for discard statement");
}
} // namespace
diff --git a/src/reader/wgsl/parser_impl_statement_test.cc b/src/reader/wgsl/parser_impl_statement_test.cc
index fdd4425..ee6df75 100644
--- a/src/reader/wgsl/parser_impl_statement_test.cc
+++ b/src/reader/wgsl/parser_impl_statement_test.cc
@@ -66,7 +66,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:7: missing ;");
+ EXPECT_EQ(p->error(), "1:7: expected ';' for return statement");
}
TEST_F(ParserImplTest, Statement_Return_Invalid) {
@@ -74,7 +74,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:8: missing ;");
+ EXPECT_EQ(p->error(), "1:8: expected ';' for return statement");
}
TEST_F(ParserImplTest, Statement_If) {
@@ -114,7 +114,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:12: missing ;");
+ EXPECT_EQ(p->error(), "1:12: expected ';' for variable declaration");
}
TEST_F(ParserImplTest, Statement_Switch) {
@@ -170,7 +170,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:6: missing ;");
+ EXPECT_EQ(p->error(), "1:6: expected ';' for assignment statement");
}
TEST_F(ParserImplTest, Statement_Break) {
@@ -186,7 +186,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:6: missing ;");
+ EXPECT_EQ(p->error(), "1:6: expected ';' for break statement");
}
TEST_F(ParserImplTest, Statement_Continue) {
@@ -202,7 +202,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:9: missing ;");
+ EXPECT_EQ(p->error(), "1:9: expected ';' for continue statement");
}
TEST_F(ParserImplTest, Statement_Discard) {
@@ -218,7 +218,7 @@
auto e = p->statement();
ASSERT_TRUE(p->has_error());
EXPECT_EQ(e, nullptr);
- EXPECT_EQ(p->error(), "1:8: missing ;");
+ EXPECT_EQ(p->error(), "1:8: expected ';' for discard statement");
}
TEST_F(ParserImplTest, Statement_Body) {
diff --git a/src/reader/wgsl/parser_impl_struct_member_test.cc b/src/reader/wgsl/parser_impl_struct_member_test.cc
index d4913c3..4c2c3a6 100644
--- a/src/reader/wgsl/parser_impl_struct_member_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_member_test.cc
@@ -106,7 +106,7 @@
auto m = p->struct_member();
ASSERT_TRUE(p->has_error());
ASSERT_EQ(m, nullptr);
- EXPECT_EQ(p->error(), "1:8: missing ; for struct member");
+ EXPECT_EQ(p->error(), "1:8: expected ';' for struct member");
}
} // namespace