tint/reader: Parse static_assert
Bug: tint:1625 Change-Id: I440de9a5f0f6817520d59d0d918acc6ac0555c42 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97963 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
fc013af417
commit
f3015a81cc
|
@ -1243,6 +1243,9 @@ Token Lexer::check_keyword(const Source& source, std::string_view str) {
|
||||||
if (str == "sampler_comparison") {
|
if (str == "sampler_comparison") {
|
||||||
return {Token::Type::kComparisonSampler, source, "sampler_comparison"};
|
return {Token::Type::kComparisonSampler, source, "sampler_comparison"};
|
||||||
}
|
}
|
||||||
|
if (str == "static_assert") {
|
||||||
|
return {Token::Type::kStaticAssert, source, "static_assert"};
|
||||||
|
}
|
||||||
if (str == "struct") {
|
if (str == "struct") {
|
||||||
return {Token::Type::kStruct, source, "struct"};
|
return {Token::Type::kStruct, source, "struct"};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1145,6 +1145,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TokenData{"return", Token::Type::kReturn},
|
TokenData{"return", Token::Type::kReturn},
|
||||||
TokenData{"sampler", Token::Type::kSampler},
|
TokenData{"sampler", Token::Type::kSampler},
|
||||||
TokenData{"sampler_comparison", Token::Type::kComparisonSampler},
|
TokenData{"sampler_comparison", Token::Type::kComparisonSampler},
|
||||||
|
TokenData{"static_assert", Token::Type::kStaticAssert},
|
||||||
TokenData{"struct", Token::Type::kStruct},
|
TokenData{"struct", Token::Type::kStruct},
|
||||||
TokenData{"switch", Token::Type::kSwitch},
|
TokenData{"switch", Token::Type::kSwitch},
|
||||||
TokenData{"texture_1d", Token::Type::kTextureSampled1d},
|
TokenData{"texture_1d", Token::Type::kTextureSampled1d},
|
||||||
|
|
|
@ -111,13 +111,13 @@ bool is_reserved(const Token& t) {
|
||||||
t == "readonly" || t == "ref" || t == "regardless" || t == "register" ||
|
t == "readonly" || t == "ref" || t == "regardless" || t == "register" ||
|
||||||
t == "reinterpret_cast" || t == "requires" || t == "resource" || t == "restrict" ||
|
t == "reinterpret_cast" || t == "requires" || t == "resource" || t == "restrict" ||
|
||||||
t == "self" || t == "set" || t == "shared" || t == "signed" || t == "sizeof" ||
|
t == "self" || t == "set" || t == "shared" || t == "signed" || t == "sizeof" ||
|
||||||
t == "smooth" || t == "snorm" || t == "static" || t == "static_assert" ||
|
t == "smooth" || t == "snorm" || t == "static" || t == "static_cast" || t == "std" ||
|
||||||
t == "static_cast" || t == "std" || t == "subroutine" || t == "super" || t == "target" ||
|
t == "subroutine" || t == "super" || t == "target" || t == "template" || t == "this" ||
|
||||||
t == "template" || t == "this" || t == "thread_local" || t == "throw" || t == "trait" ||
|
t == "thread_local" || t == "throw" || t == "trait" || t == "try" || t == "typedef" ||
|
||||||
t == "try" || t == "typedef" || t == "typeid" || t == "typename" || t == "typeof" ||
|
t == "typeid" || t == "typename" || t == "typeof" || t == "union" || t == "unless" ||
|
||||||
t == "union" || t == "unless" || t == "unorm" || t == "unsafe" || t == "unsized" ||
|
t == "unorm" || t == "unsafe" || t == "unsized" || t == "use" || t == "using" ||
|
||||||
t == "use" || t == "using" || t == "varying" || t == "virtual" || t == "volatile" ||
|
t == "varying" || t == "virtual" || t == "volatile" || t == "wgsl" || t == "where" ||
|
||||||
t == "wgsl" || t == "where" || t == "with" || t == "writeonly" || t == "yield";
|
t == "with" || t == "writeonly" || t == "yield";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enter-exit counters for block token types.
|
/// Enter-exit counters for block token types.
|
||||||
|
@ -438,11 +438,12 @@ Maybe<bool> ParserImpl::enable_directive() {
|
||||||
|
|
||||||
// global_decl
|
// global_decl
|
||||||
// : SEMICOLON
|
// : SEMICOLON
|
||||||
// | global_variable_decl SEMICLON
|
// | global_variable_decl SEMICOLON
|
||||||
// | global_constant_decl SEMICOLON
|
// | global_constant_decl SEMICOLON
|
||||||
// | type_alias SEMICOLON
|
// | type_alias SEMICOLON
|
||||||
// | struct_decl
|
// | struct_decl
|
||||||
// | function_decl
|
// | function_decl
|
||||||
|
// | static_assert_statement SEMICOLON
|
||||||
Maybe<bool> ParserImpl::global_decl() {
|
Maybe<bool> ParserImpl::global_decl() {
|
||||||
if (match(Token::Type::kSemicolon) || match(Token::Type::kEOF)) {
|
if (match(Token::Type::kSemicolon) || match(Token::Type::kEOF)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -476,7 +477,6 @@ Maybe<bool> ParserImpl::global_decl() {
|
||||||
if (gc.errored) {
|
if (gc.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gc.matched) {
|
if (gc.matched) {
|
||||||
// Avoid the cost of the string allocation for the common no-error case
|
// Avoid the cost of the string allocation for the common no-error case
|
||||||
if (!peek().Is(Token::Type::kSemicolon)) {
|
if (!peek().Is(Token::Type::kSemicolon)) {
|
||||||
|
@ -494,7 +494,6 @@ Maybe<bool> ParserImpl::global_decl() {
|
||||||
if (ta.errored) {
|
if (ta.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ta.matched) {
|
if (ta.matched) {
|
||||||
if (!expect("type alias", Token::Type::kSemicolon)) {
|
if (!expect("type alias", Token::Type::kSemicolon)) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
|
@ -508,12 +507,23 @@ Maybe<bool> ParserImpl::global_decl() {
|
||||||
if (str.errored) {
|
if (str.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str.matched) {
|
if (str.matched) {
|
||||||
builder_.AST().AddTypeDecl(str.value);
|
builder_.AST().AddTypeDecl(str.value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto assertion = static_assert_stmt();
|
||||||
|
if (assertion.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
if (assertion.matched) {
|
||||||
|
builder_.AST().AddStaticAssert(assertion.value);
|
||||||
|
if (!expect("static assertion declaration", Token::Type::kSemicolon)) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return Failure::kNoMatch;
|
return Failure::kNoMatch;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1365,6 +1375,24 @@ Expect<ast::StructMember*> ParserImpl::expect_struct_member() {
|
||||||
decl->type, std::move(attrs.value));
|
decl->type, std::move(attrs.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maybe<const ast::StaticAssert*> ParserImpl::static_assert_stmt() {
|
||||||
|
Source start;
|
||||||
|
if (!match(Token::Type::kStaticAssert, &start)) {
|
||||||
|
return Failure::kNoMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto condition = logical_or_expression();
|
||||||
|
if (condition.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
if (!condition.matched) {
|
||||||
|
return add_error(peek(), "unable to parse condition expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
Source source = make_source_range_from(start);
|
||||||
|
return create<ast::StaticAssert>(source, condition.value);
|
||||||
|
}
|
||||||
|
|
||||||
// function_decl
|
// function_decl
|
||||||
// : function_header body_stmt
|
// : function_header body_stmt
|
||||||
Maybe<const ast::Function*> ParserImpl::function_decl(AttributeList& attrs) {
|
Maybe<const ast::Function*> ParserImpl::function_decl(AttributeList& attrs) {
|
||||||
|
@ -1613,12 +1641,13 @@ Expect<ParserImpl::StatementList> ParserImpl::expect_statements() {
|
||||||
// | assignment_stmt SEMICOLON
|
// | assignment_stmt SEMICOLON
|
||||||
// | increment_stmt SEMICOLON
|
// | increment_stmt SEMICOLON
|
||||||
// | decrement_stmt SEMICOLON
|
// | decrement_stmt SEMICOLON
|
||||||
|
// | static_assert_stmt SEMICOLON
|
||||||
Maybe<const ast::Statement*> ParserImpl::statement() {
|
Maybe<const ast::Statement*> ParserImpl::statement() {
|
||||||
while (match(Token::Type::kSemicolon)) {
|
while (match(Token::Type::kSemicolon)) {
|
||||||
// Skip empty statements
|
// Skip empty statements
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-block statments that error can resynchronize on semicolon.
|
// Non-block statements that error can resynchronize on semicolon.
|
||||||
auto stmt = sync(Token::Type::kSemicolon, [&] { return non_block_statement(); });
|
auto stmt = sync(Token::Type::kSemicolon, [&] { return non_block_statement(); });
|
||||||
|
|
||||||
if (stmt.errored) {
|
if (stmt.errored) {
|
||||||
|
@ -1739,6 +1768,14 @@ Maybe<const ast::Statement*> ParserImpl::non_block_statement() {
|
||||||
return assign.value;
|
return assign.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto stmt_static_assert = static_assert_stmt();
|
||||||
|
if (stmt_static_assert.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
if (stmt_static_assert.matched) {
|
||||||
|
return stmt_static_assert.value;
|
||||||
|
}
|
||||||
|
|
||||||
Source source;
|
Source source;
|
||||||
if (match(Token::Type::kDiscard, &source)) {
|
if (match(Token::Type::kDiscard, &source)) {
|
||||||
return create<ast::DiscardStatement>(source);
|
return create<ast::DiscardStatement>(source);
|
||||||
|
|
|
@ -472,6 +472,9 @@ class ParserImpl {
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @param use a description of what was being parsed if an error was raised
|
||||||
/// @returns returns the texel format or kNone if none matched.
|
/// @returns returns the texel format or kNone if none matched.
|
||||||
Expect<ast::TexelFormat> expect_texel_format(std::string_view use);
|
Expect<ast::TexelFormat> expect_texel_format(std::string_view use);
|
||||||
|
/// Parses a `static_assert_statement` grammar element
|
||||||
|
/// @returns returns the static assert, if it matched.
|
||||||
|
Maybe<const ast::StaticAssert*> static_assert_stmt();
|
||||||
/// Parses a `function_header` grammar element
|
/// Parses a `function_header` grammar element
|
||||||
/// @returns the parsed function header
|
/// @returns the parsed function header
|
||||||
Maybe<FunctionHeader> function_header();
|
Maybe<FunctionHeader> function_header();
|
||||||
|
|
|
@ -306,6 +306,51 @@ fn f() { for (var i : i32 = 0; i < 8; i=i+1) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, FunctionDeclStaticAssertMissingCondThenEOF) {
|
||||||
|
EXPECT("fn f() { static_assert }", R"(test.wgsl:1:24 error: unable to parse condition expression
|
||||||
|
fn f() { static_assert }
|
||||||
|
^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, FunctionDeclStaticAssertMissingCondThenSemicolon) {
|
||||||
|
EXPECT("fn f() { static_assert; }",
|
||||||
|
R"(test.wgsl:1:23 error: unable to parse condition expression
|
||||||
|
fn f() { static_assert; }
|
||||||
|
^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, FunctionDeclStaticAssertMissingCondThenLet) {
|
||||||
|
EXPECT("fn f() { static_assert\nlet x = 0; }",
|
||||||
|
R"(test.wgsl:2:1 error: unable to parse condition expression
|
||||||
|
let x = 0; }
|
||||||
|
^^^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, FunctionDeclStaticAssertMissingLParen) {
|
||||||
|
EXPECT("fn f() { static_assert true);", R"(test.wgsl:1:28 error: expected ';' for statement
|
||||||
|
fn f() { static_assert true);
|
||||||
|
^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, FunctionDeclStaticAssertMissingRParen) {
|
||||||
|
EXPECT("fn f() { static_assert (true;", R"(test.wgsl:1:29 error: expected ')'
|
||||||
|
fn f() { static_assert (true;
|
||||||
|
^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, FunctionDeclStaticAssertMissingSemicolon) {
|
||||||
|
EXPECT("fn f() { static_assert true }",
|
||||||
|
R"(test.wgsl:1:29 error: expected ';' for statement
|
||||||
|
fn f() { static_assert true }
|
||||||
|
^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(crbug.com/tint/1503): Remove this when @stage is removed
|
// TODO(crbug.com/tint/1503): Remove this when @stage is removed
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclStageMissingLParen) {
|
TEST_F(ParserImplErrorTest, FunctionDeclStageMissingLParen) {
|
||||||
EXPECT("@stage vertex) fn f() {}",
|
EXPECT("@stage vertex) fn f() {}",
|
||||||
|
@ -697,6 +742,50 @@ var x : texture_multisampled_2d<1>;
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, GlobalDeclStaticAssertMissingCondThenEOF) {
|
||||||
|
EXPECT("static_assert", R"(test.wgsl:1:14 error: unable to parse condition expression
|
||||||
|
static_assert
|
||||||
|
^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, GlobalDeclStaticAssertMissingCondThenSemicolon) {
|
||||||
|
EXPECT("static_assert;", R"(test.wgsl:1:14 error: unable to parse condition expression
|
||||||
|
static_assert;
|
||||||
|
^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, GlobalDeclStaticAssertMissingCondThenAlias) {
|
||||||
|
EXPECT("static_assert\ntype T = i32;",
|
||||||
|
R"(test.wgsl:2:1 error: unable to parse condition expression
|
||||||
|
type T = i32;
|
||||||
|
^^^^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, GlobalDeclStaticAssertMissingLParen) {
|
||||||
|
EXPECT("static_assert true);", R"(test.wgsl:1:19 error: expected ';' for static assertion declaration
|
||||||
|
static_assert true);
|
||||||
|
^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, GlobalDeclStaticAssertMissingRParen) {
|
||||||
|
EXPECT("static_assert (true;", R"(test.wgsl:1:20 error: expected ')'
|
||||||
|
static_assert (true;
|
||||||
|
^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplErrorTest, GlobalDeclStaticAssertMissingSemicolon) {
|
||||||
|
EXPECT("static_assert true static_assert true;",
|
||||||
|
R"(test.wgsl:1:20 error: expected ';' for static assertion declaration
|
||||||
|
static_assert true static_assert true;
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclStorageTextureMissingLessThan) {
|
TEST_F(ParserImplErrorTest, GlobalDeclStorageTextureMissingLessThan) {
|
||||||
EXPECT("var x : texture_storage_2d;",
|
EXPECT("var x : texture_storage_2d;",
|
||||||
R"(test.wgsl:1:27 error: expected '<' for storage texture type
|
R"(test.wgsl:1:27 error: expected '<' for storage texture type
|
||||||
|
|
|
@ -233,5 +233,47 @@ TEST_F(ParserImplTest, GlobalDecl_Struct_Invalid) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, GlobalDecl_StaticAssert_WithParen) {
|
||||||
|
auto p = parser("static_assert(true);");
|
||||||
|
p->global_decl();
|
||||||
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
|
auto program = p->program();
|
||||||
|
ASSERT_EQ(program.AST().StaticAsserts().Length(), 1u);
|
||||||
|
auto* sa = program.AST().StaticAsserts()[0];
|
||||||
|
EXPECT_EQ(sa->source.range.begin.line, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.begin.column, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.end.line, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.end.column, 20u);
|
||||||
|
|
||||||
|
EXPECT_TRUE(sa->condition->Is<ast::BoolLiteralExpression>());
|
||||||
|
EXPECT_EQ(sa->condition->source.range.begin.line, 1u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.begin.column, 15u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.end.line, 1u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.end.column, 19u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, GlobalDecl_StaticAssert_WithoutParen) {
|
||||||
|
auto p = parser("static_assert true;");
|
||||||
|
p->global_decl();
|
||||||
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
|
||||||
|
auto program = p->program();
|
||||||
|
ASSERT_EQ(program.AST().StaticAsserts().Length(), 1u);
|
||||||
|
auto* sa = program.AST().StaticAsserts()[0];
|
||||||
|
EXPECT_TRUE(sa->condition->Is<ast::BoolLiteralExpression>());
|
||||||
|
|
||||||
|
EXPECT_EQ(sa->source.range.begin.line, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.begin.column, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.end.line, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.end.column, 20u);
|
||||||
|
|
||||||
|
EXPECT_TRUE(sa->condition->Is<ast::BoolLiteralExpression>());
|
||||||
|
EXPECT_EQ(sa->condition->source.range.begin.line, 1u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.begin.column, 16u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.end.line, 1u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.end.column, 20u);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::reader::wgsl
|
} // namespace tint::reader::wgsl
|
||||||
|
|
|
@ -215,7 +215,6 @@ INSTANTIATE_TEST_SUITE_P(ParserImplReservedKeywordTest,
|
||||||
"smooth",
|
"smooth",
|
||||||
"snorm",
|
"snorm",
|
||||||
"static",
|
"static",
|
||||||
"static_assert",
|
|
||||||
"static_cast",
|
"static_cast",
|
||||||
"std",
|
"std",
|
||||||
"subroutine",
|
"subroutine",
|
||||||
|
|
|
@ -272,5 +272,47 @@ TEST_F(ParserImplTest, Statement_Body_Invalid) {
|
||||||
EXPECT_EQ(p->error(), "1:3: expected '}'");
|
EXPECT_EQ(p->error(), "1:3: expected '}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, Statement_StaticAssert_WithParen) {
|
||||||
|
auto p = parser("static_assert(true);");
|
||||||
|
auto e = p->statement();
|
||||||
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
|
||||||
|
auto* sa = As<ast::StaticAssert>(e.value);
|
||||||
|
ASSERT_NE(sa, nullptr);
|
||||||
|
EXPECT_EQ(sa->source.range.begin.line, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.begin.column, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.end.line, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.end.column, 20u);
|
||||||
|
|
||||||
|
EXPECT_TRUE(sa->condition->Is<ast::BoolLiteralExpression>());
|
||||||
|
EXPECT_EQ(sa->condition->source.range.begin.line, 1u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.begin.column, 15u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.end.line, 1u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.end.column, 19u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, Statement_StaticAssert_WithoutParen) {
|
||||||
|
auto p = parser("static_assert true;");
|
||||||
|
auto e = p->statement();
|
||||||
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
|
||||||
|
auto* sa = As<ast::StaticAssert>(e.value);
|
||||||
|
ASSERT_NE(sa, nullptr);
|
||||||
|
EXPECT_EQ(sa->source.range.begin.line, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.begin.column, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.end.line, 1u);
|
||||||
|
EXPECT_EQ(sa->source.range.end.column, 20u);
|
||||||
|
|
||||||
|
EXPECT_TRUE(sa->condition->Is<ast::BoolLiteralExpression>());
|
||||||
|
EXPECT_EQ(sa->condition->source.range.begin.line, 1u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.begin.column, 16u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.end.line, 1u);
|
||||||
|
EXPECT_EQ(sa->condition->source.range.end.column, 20u);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::reader::wgsl
|
} // namespace tint::reader::wgsl
|
||||||
|
|
|
@ -209,6 +209,8 @@ std::string_view Token::TypeToName(Type type) {
|
||||||
return "sampler";
|
return "sampler";
|
||||||
case Token::Type::kComparisonSampler:
|
case Token::Type::kComparisonSampler:
|
||||||
return "sampler_comparison";
|
return "sampler_comparison";
|
||||||
|
case Token::Type::kStaticAssert:
|
||||||
|
return "static_assert";
|
||||||
case Token::Type::kStruct:
|
case Token::Type::kStruct:
|
||||||
return "struct";
|
return "struct";
|
||||||
case Token::Type::kSwitch:
|
case Token::Type::kSwitch:
|
||||||
|
|
|
@ -219,6 +219,8 @@ class Token {
|
||||||
kSampler,
|
kSampler,
|
||||||
/// A 'sampler_comparison'
|
/// A 'sampler_comparison'
|
||||||
kComparisonSampler,
|
kComparisonSampler,
|
||||||
|
/// A 'static_assert'
|
||||||
|
kStaticAssert,
|
||||||
/// A 'struct'
|
/// A 'struct'
|
||||||
kStruct,
|
kStruct,
|
||||||
/// A 'switch'
|
/// A 'switch'
|
||||||
|
|
Loading…
Reference in New Issue