parser: fix wgsl expect_const_expr()
Bug: tint:1025 Change-Id: I35aab866ffce57681662f59e4b8e701bb03cf718 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/59220 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Sarah Mashayekhi <sarahmashay@google.com>
This commit is contained in:
parent
f7e73d4ee3
commit
f76c227cee
|
@ -2843,48 +2843,51 @@ Maybe<ast::Literal*> ParserImpl::const_literal() {
|
|||
// | const_literal
|
||||
Expect<ast::ConstructorExpression*> ParserImpl::expect_const_expr() {
|
||||
auto t = peek();
|
||||
|
||||
auto source = t.source();
|
||||
|
||||
auto type = type_decl();
|
||||
if (type.errored)
|
||||
return Failure::kErrored;
|
||||
if (type.matched) {
|
||||
auto params = expect_paren_block(
|
||||
"type constructor", [&]() -> Expect<ast::ExpressionList> {
|
||||
ast::ExpressionList list;
|
||||
while (continue_parsing()) {
|
||||
if (peek_is(Token::Type::kParenRight)) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto arg = expect_const_expr();
|
||||
if (arg.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
list.emplace_back(arg.value);
|
||||
|
||||
if (!match(Token::Type::kComma)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
});
|
||||
|
||||
if (params.errored)
|
||||
if (t.IsLiteral()) {
|
||||
auto lit = const_literal();
|
||||
if (lit.errored)
|
||||
return Failure::kErrored;
|
||||
if (!lit.matched)
|
||||
return add_error(peek(), "unable to parse constant literal");
|
||||
|
||||
return create<ast::TypeConstructorExpression>(source, type.value,
|
||||
params.value);
|
||||
return create<ast::ScalarConstructorExpression>(source, lit.value);
|
||||
} else if (!t.IsIdentifier() || get_type(t.to_str())) {
|
||||
if (peek_is(Token::Type::kParenLeft, 1) ||
|
||||
peek_is(Token::Type::kLessThan, 1)) {
|
||||
auto type = expect_type("const_expr");
|
||||
if (type.errored)
|
||||
return Failure::kErrored;
|
||||
|
||||
auto params = expect_paren_block(
|
||||
"type constructor", [&]() -> Expect<ast::ExpressionList> {
|
||||
ast::ExpressionList list;
|
||||
while (continue_parsing()) {
|
||||
if (peek_is(Token::Type::kParenRight)) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto arg = expect_const_expr();
|
||||
if (arg.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
list.emplace_back(arg.value);
|
||||
|
||||
if (!match(Token::Type::kComma)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
});
|
||||
|
||||
if (params.errored)
|
||||
return Failure::kErrored;
|
||||
|
||||
return create<ast::TypeConstructorExpression>(source, type.value,
|
||||
params.value);
|
||||
}
|
||||
}
|
||||
|
||||
auto lit = const_literal();
|
||||
if (lit.errored)
|
||||
return Failure::kErrored;
|
||||
if (!lit.matched)
|
||||
return add_error(peek(), "unable to parse constant literal");
|
||||
|
||||
return create<ast::ScalarConstructorExpression>(source, lit.value);
|
||||
return add_error(peek(), "unable to parse const_expr");
|
||||
}
|
||||
|
||||
Maybe<ast::DecorationList> ParserImpl::decoration_list() {
|
||||
|
|
|
@ -112,7 +112,7 @@ TEST_F(ParserImplTest, ConstExpr_InvalidExpr) {
|
|||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_TRUE(e.errored);
|
||||
ASSERT_EQ(e.value, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:15: unable to parse constant literal");
|
||||
EXPECT_EQ(p->error(), "1:15: invalid type for const_expr");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_ConstLiteral) {
|
||||
|
@ -134,7 +134,29 @@ TEST_F(ParserImplTest, ConstExpr_ConstLiteral_Invalid) {
|
|||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_TRUE(e.errored);
|
||||
ASSERT_EQ(e.value, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:1: unknown type 'invalid'");
|
||||
EXPECT_EQ(p->error(), "1:1: unable to parse const_expr");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_RegisteredType) {
|
||||
auto p = parser("S(0)");
|
||||
|
||||
auto* mem = Member("m", ty.i32(), ast::DecorationList{});
|
||||
auto* s = Structure(Sym("S"), {mem});
|
||||
p->register_type("S", s);
|
||||
|
||||
auto e = p->expect_const_expr();
|
||||
ASSERT_FALSE(e.errored);
|
||||
ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
|
||||
ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_NotRegisteredType) {
|
||||
auto p = parser("S(0)");
|
||||
auto e = p->expect_const_expr();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_TRUE(e.errored);
|
||||
ASSERT_EQ(e.value, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:1: unable to parse const_expr");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, ConstExpr_Recursion) {
|
||||
|
|
|
@ -434,7 +434,7 @@ TEST_F(ParserImplErrorTest, FunctionMissingOpenLine) {
|
|||
var a : f32 = bar[0];
|
||||
return;
|
||||
})",
|
||||
"test.wgsl:2:17 error: unknown type 'bar'\n"
|
||||
"test.wgsl:2:17 error: unable to parse const_expr\n"
|
||||
" var a : f32 = bar[0];\n"
|
||||
" ^^^\n"
|
||||
"\n"
|
||||
|
@ -473,11 +473,43 @@ TEST_F(ParserImplErrorTest, GlobalDeclConstMissingRParen) {
|
|||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclConstBadConstLiteral) {
|
||||
EXPECT("let i : vec2<i32> = vec2<i32>(!);",
|
||||
"test.wgsl:1:31 error: unable to parse constant literal\n"
|
||||
"test.wgsl:1:31 error: unable to parse const_expr\n"
|
||||
"let i : vec2<i32> = vec2<i32>(!);\n"
|
||||
" ^\n");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclConstBadConstLiteralSpaceLessThan) {
|
||||
EXPECT("let i = 1 < 2;",
|
||||
"test.wgsl:1:11 error: expected \';\' for let declaration\n"
|
||||
"let i = 1 < 2;\n"
|
||||
" ^\n");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclConstNotConstExpr) {
|
||||
EXPECT(
|
||||
"let a = 1;\n"
|
||||
"let b = a;",
|
||||
"test.wgsl:2:9 error: unable to parse const_expr\n"
|
||||
"let b = a;\n"
|
||||
" ^\n");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclConstNotConstExprWithParn) {
|
||||
EXPECT(
|
||||
"let a = 1;\n"
|
||||
"let b = a();",
|
||||
"test.wgsl:2:9 error: unable to parse const_expr\n"
|
||||
"let b = a();\n"
|
||||
" ^\n");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclConstConstExprRegisteredType) {
|
||||
EXPECT("let a = S0(0);",
|
||||
"test.wgsl:1:9 error: unable to parse const_expr\n"
|
||||
"let a = S0(0);\n"
|
||||
" ^^\n");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, GlobalDeclConstExprMaxDepth) {
|
||||
uint32_t kMaxDepth = 128;
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_FALSE(e.matched);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:15: unable to parse constant literal");
|
||||
EXPECT_EQ(p->error(), "1:15: invalid type for const_expr");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
|
||||
|
@ -111,7 +111,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_FALSE(e.matched);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:14: unable to parse constant literal");
|
||||
EXPECT_EQ(p->error(), "1:14: unable to parse const_expr");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDec_Override_WithId) {
|
||||
|
|
|
@ -152,7 +152,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_InvalidConstExpr) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_FALSE(e.matched);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:24: unable to parse constant literal");
|
||||
EXPECT_EQ(p->error(), "1:24: invalid type for const_expr");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
|
||||
|
|
|
@ -372,7 +372,12 @@ class Token {
|
|||
bool IsEof() const { return type_ == Type::kEOF; }
|
||||
/// @returns true if the token is an identifier
|
||||
bool IsIdentifier() const { return type_ == Type::kIdentifier; }
|
||||
|
||||
/// @returns true if the token is a literal
|
||||
bool IsLiteral() const {
|
||||
return type_ == Type::kSintLiteral || type_ == Type::kFalse ||
|
||||
type_ == Type::kUintLiteral || type_ == Type::kTrue ||
|
||||
type_ == Type::kFloatLiteral;
|
||||
}
|
||||
/// @returns true if token is a 'matNxM'
|
||||
bool IsMatrix() const {
|
||||
return type_ == Type::kMat2x2 || type_ == Type::kMat2x3 ||
|
||||
|
|
Loading…
Reference in New Issue