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
|
// | const_literal
|
||||||
Expect<ast::ConstructorExpression*> ParserImpl::expect_const_expr() {
|
Expect<ast::ConstructorExpression*> ParserImpl::expect_const_expr() {
|
||||||
auto t = peek();
|
auto t = peek();
|
||||||
|
|
||||||
auto source = t.source();
|
auto source = t.source();
|
||||||
|
if (t.IsLiteral()) {
|
||||||
auto type = type_decl();
|
auto lit = const_literal();
|
||||||
if (type.errored)
|
if (lit.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)
|
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
if (!lit.matched)
|
||||||
|
return add_error(peek(), "unable to parse constant literal");
|
||||||
|
|
||||||
return create<ast::TypeConstructorExpression>(source, type.value,
|
return create<ast::ScalarConstructorExpression>(source, lit.value);
|
||||||
params.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return add_error(peek(), "unable to parse const_expr");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<ast::DecorationList> ParserImpl::decoration_list() {
|
Maybe<ast::DecorationList> ParserImpl::decoration_list() {
|
||||||
|
|
|
@ -112,7 +112,7 @@ TEST_F(ParserImplTest, ConstExpr_InvalidExpr) {
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(e.errored);
|
ASSERT_TRUE(e.errored);
|
||||||
ASSERT_EQ(e.value, nullptr);
|
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) {
|
TEST_F(ParserImplTest, ConstExpr_ConstLiteral) {
|
||||||
|
@ -134,7 +134,29 @@ TEST_F(ParserImplTest, ConstExpr_ConstLiteral_Invalid) {
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(e.errored);
|
ASSERT_TRUE(e.errored);
|
||||||
ASSERT_EQ(e.value, nullptr);
|
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) {
|
TEST_F(ParserImplTest, ConstExpr_Recursion) {
|
||||||
|
|
|
@ -434,7 +434,7 @@ TEST_F(ParserImplErrorTest, FunctionMissingOpenLine) {
|
||||||
var a : f32 = bar[0];
|
var a : f32 = bar[0];
|
||||||
return;
|
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"
|
" var a : f32 = bar[0];\n"
|
||||||
" ^^^\n"
|
" ^^^\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -473,11 +473,43 @@ TEST_F(ParserImplErrorTest, GlobalDeclConstMissingRParen) {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclConstBadConstLiteral) {
|
TEST_F(ParserImplErrorTest, GlobalDeclConstBadConstLiteral) {
|
||||||
EXPECT("let i : vec2<i32> = vec2<i32>(!);",
|
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"
|
"let i : vec2<i32> = vec2<i32>(!);\n"
|
||||||
" ^\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) {
|
TEST_F(ParserImplErrorTest, GlobalDeclConstExprMaxDepth) {
|
||||||
uint32_t kMaxDepth = 128;
|
uint32_t kMaxDepth = 128;
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_FALSE(e.matched);
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
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) {
|
TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
|
||||||
|
@ -111,7 +111,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_FALSE(e.matched);
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
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) {
|
TEST_F(ParserImplTest, GlobalConstantDec_Override_WithId) {
|
||||||
|
|
|
@ -152,7 +152,7 @@ TEST_F(ParserImplTest, GlobalVariableDecl_InvalidConstExpr) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_FALSE(e.matched);
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
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) {
|
TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
|
||||||
|
|
|
@ -372,7 +372,12 @@ class Token {
|
||||||
bool IsEof() const { return type_ == Type::kEOF; }
|
bool IsEof() const { return type_ == Type::kEOF; }
|
||||||
/// @returns true if the token is an identifier
|
/// @returns true if the token is an identifier
|
||||||
bool IsIdentifier() const { return type_ == Type::kIdentifier; }
|
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'
|
/// @returns true if token is a 'matNxM'
|
||||||
bool IsMatrix() const {
|
bool IsMatrix() const {
|
||||||
return type_ == Type::kMat2x2 || type_ == Type::kMat2x3 ||
|
return type_ == Type::kMat2x2 || type_ == Type::kMat2x3 ||
|
||||||
|
|
Loading…
Reference in New Issue