Parse void function call.
This CL updates the WGSL parser to handle a void function call. Fixes: tint:45 Change-Id: If5b2a4b9e62f0b10e0f2e2e10c0ca2586c5268e8 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25322 Reviewed-by: Ryan Harrison <rharrison@chromium.org>
This commit is contained in:
parent
e5228407f4
commit
fbbc617888
1
BUILD.gn
1
BUILD.gn
|
@ -838,6 +838,7 @@ source_set("tint_unittests_wgsl_reader_src") {
|
||||||
"src/reader/wgsl/parser_impl_assignment_stmt_test.cc",
|
"src/reader/wgsl/parser_impl_assignment_stmt_test.cc",
|
||||||
"src/reader/wgsl/parser_impl_body_stmt_test.cc",
|
"src/reader/wgsl/parser_impl_body_stmt_test.cc",
|
||||||
"src/reader/wgsl/parser_impl_break_stmt_test.cc",
|
"src/reader/wgsl/parser_impl_break_stmt_test.cc",
|
||||||
|
"src/reader/wgsl/parser_impl_call_stmt_test.cc",
|
||||||
"src/reader/wgsl/parser_impl_case_body_test.cc",
|
"src/reader/wgsl/parser_impl_case_body_test.cc",
|
||||||
"src/reader/wgsl/parser_impl_const_expr_test.cc",
|
"src/reader/wgsl/parser_impl_const_expr_test.cc",
|
||||||
"src/reader/wgsl/parser_impl_const_literal_test.cc",
|
"src/reader/wgsl/parser_impl_const_literal_test.cc",
|
||||||
|
|
|
@ -385,6 +385,7 @@ if(${TINT_BUILD_WGSL_READER})
|
||||||
reader/wgsl/parser_impl_assignment_stmt_test.cc
|
reader/wgsl/parser_impl_assignment_stmt_test.cc
|
||||||
reader/wgsl/parser_impl_body_stmt_test.cc
|
reader/wgsl/parser_impl_body_stmt_test.cc
|
||||||
reader/wgsl/parser_impl_break_stmt_test.cc
|
reader/wgsl/parser_impl_break_stmt_test.cc
|
||||||
|
reader/wgsl/parser_impl_call_stmt_test.cc
|
||||||
reader/wgsl/parser_impl_case_body_test.cc
|
reader/wgsl/parser_impl_case_body_test.cc
|
||||||
reader/wgsl/parser_impl_const_expr_test.cc
|
reader/wgsl/parser_impl_const_expr_test.cc
|
||||||
reader/wgsl/parser_impl_const_literal_test.cc
|
reader/wgsl/parser_impl_const_literal_test.cc
|
||||||
|
|
|
@ -1422,6 +1422,7 @@ ast::StatementList ParserImpl::statements() {
|
||||||
// | if_stmt
|
// | if_stmt
|
||||||
// | switch_stmt
|
// | switch_stmt
|
||||||
// | loop_stmt
|
// | loop_stmt
|
||||||
|
// | func_call_stmt SEMICOLON
|
||||||
// | variable_stmt SEMICOLON
|
// | variable_stmt SEMICOLON
|
||||||
// | break_stmt SEMICOLON
|
// | break_stmt SEMICOLON
|
||||||
// | continue_stmt SEMICOLON
|
// | continue_stmt SEMICOLON
|
||||||
|
@ -1464,6 +1465,18 @@ std::unique_ptr<ast::Statement> ParserImpl::statement() {
|
||||||
if (loop != nullptr)
|
if (loop != nullptr)
|
||||||
return loop;
|
return loop;
|
||||||
|
|
||||||
|
auto func = func_call_stmt();
|
||||||
|
if (has_error())
|
||||||
|
return nullptr;
|
||||||
|
if (func != nullptr) {
|
||||||
|
t = next();
|
||||||
|
if (!t.IsSemicolon()) {
|
||||||
|
set_error(t, "missing ;");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
auto var = variable_stmt();
|
auto var = variable_stmt();
|
||||||
if (has_error())
|
if (has_error())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1908,6 +1921,41 @@ std::unique_ptr<ast::LoopStatement> ParserImpl::loop_stmt() {
|
||||||
std::move(continuing));
|
std::move(continuing));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func_call_stmt
|
||||||
|
// : IDENT PAREN_LEFT argument_expression_list* PAREN_RIGHT
|
||||||
|
std::unique_ptr<ast::CallStatement> ParserImpl::func_call_stmt() {
|
||||||
|
auto t = peek();
|
||||||
|
auto t2 = peek(1);
|
||||||
|
if (!t.IsIdentifier() || !t2.IsParenLeft())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto source = t.source();
|
||||||
|
|
||||||
|
next(); // Consume the peek
|
||||||
|
next(); // Consume the 2nd peek
|
||||||
|
|
||||||
|
auto name = t.to_str();
|
||||||
|
|
||||||
|
t = peek();
|
||||||
|
ast::ExpressionList params;
|
||||||
|
if (!t.IsParenRight() && !t.IsEof()) {
|
||||||
|
params = argument_expression_list();
|
||||||
|
if (has_error())
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
t = next();
|
||||||
|
if (!t.IsParenRight()) {
|
||||||
|
set_error(t, "missing ) for call statement");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_unique<ast::CallStatement>(
|
||||||
|
std::make_unique<ast::CallExpression>(
|
||||||
|
source, std::make_unique<ast::IdentifierExpression>(name),
|
||||||
|
std::move(params)));
|
||||||
|
}
|
||||||
|
|
||||||
// break_stmt
|
// break_stmt
|
||||||
// : BREAK
|
// : BREAK
|
||||||
std::unique_ptr<ast::BreakStatement> ParserImpl::break_stmt() {
|
std::unique_ptr<ast::BreakStatement> ParserImpl::break_stmt() {
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "src/ast/assignment_statement.h"
|
#include "src/ast/assignment_statement.h"
|
||||||
#include "src/ast/builtin.h"
|
#include "src/ast/builtin.h"
|
||||||
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/constructor_expression.h"
|
#include "src/ast/constructor_expression.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
@ -219,6 +220,9 @@ class ParserImpl {
|
||||||
/// Parses a `case_body` grammar element
|
/// Parses a `case_body` grammar element
|
||||||
/// @returns the parsed statements
|
/// @returns the parsed statements
|
||||||
ast::StatementList case_body();
|
ast::StatementList case_body();
|
||||||
|
/// Parses a `func_call_stmt` grammar element
|
||||||
|
/// @returns the parsed function call or nullptr
|
||||||
|
std::unique_ptr<ast::CallStatement> func_call_stmt();
|
||||||
/// Parses a `loop_stmt` grammar element
|
/// Parses a `loop_stmt` grammar element
|
||||||
/// @returns the parsed loop or nullptr
|
/// @returns the parsed loop or nullptr
|
||||||
std::unique_ptr<ast::LoopStatement> loop_stmt();
|
std::unique_ptr<ast::LoopStatement> loop_stmt();
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
// Copyright 2020 The Tint Authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/ast/call_expression.h"
|
||||||
|
#include "src/ast/call_statement.h"
|
||||||
|
#include "src/ast/identifier_expression.h"
|
||||||
|
#include "src/reader/wgsl/parser_impl.h"
|
||||||
|
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||||
|
|
||||||
|
namespace tint {
|
||||||
|
namespace reader {
|
||||||
|
namespace wgsl {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, Statement_Call) {
|
||||||
|
auto* p = parser("a();");
|
||||||
|
auto e = p->statement();
|
||||||
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e, nullptr);
|
||||||
|
|
||||||
|
ASSERT_TRUE(e->IsCall());
|
||||||
|
auto* c = e->AsCall()->expr();
|
||||||
|
|
||||||
|
ASSERT_TRUE(c->func()->IsIdentifier());
|
||||||
|
auto* func = c->func()->AsIdentifier();
|
||||||
|
EXPECT_EQ(func->name(), "a");
|
||||||
|
|
||||||
|
EXPECT_EQ(c->params().size(), 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, Statement_Call_WithParams) {
|
||||||
|
auto* p = parser("a(1, b, 2 + 3 / b);");
|
||||||
|
auto e = p->statement();
|
||||||
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e, nullptr);
|
||||||
|
|
||||||
|
ASSERT_TRUE(e->IsCall());
|
||||||
|
auto* c = e->AsCall()->expr();
|
||||||
|
|
||||||
|
ASSERT_TRUE(c->func()->IsIdentifier());
|
||||||
|
auto* func = c->func()->AsIdentifier();
|
||||||
|
EXPECT_EQ(func->name(), "a");
|
||||||
|
|
||||||
|
EXPECT_EQ(c->params().size(), 3u);
|
||||||
|
EXPECT_TRUE(c->params()[0]->IsConstructor());
|
||||||
|
EXPECT_TRUE(c->params()[1]->IsIdentifier());
|
||||||
|
EXPECT_TRUE(c->params()[2]->IsBinary());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, Statement_Call_Missing_RightParen) {
|
||||||
|
auto* p = parser("a(");
|
||||||
|
auto e = p->statement();
|
||||||
|
ASSERT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(p->error(), "1:3: missing ) for call statement");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, Statement_Call_Missing_Semi) {
|
||||||
|
auto* p = parser("a()");
|
||||||
|
auto e = p->statement();
|
||||||
|
ASSERT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(p->error(), "1:4: missing ;");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, Statement_Call_Bad_ArgList) {
|
||||||
|
auto* p = parser("a(b c);");
|
||||||
|
auto e = p->statement();
|
||||||
|
ASSERT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(p->error(), "1:5: missing ) for call statement");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace wgsl
|
||||||
|
} // namespace reader
|
||||||
|
} // namespace tint
|
|
@ -14,9 +14,14 @@
|
||||||
|
|
||||||
[[location 0]] var<out> gl_FragColor : vec4<f32>;
|
[[location 0]] var<out> gl_FragColor : vec4<f32>;
|
||||||
|
|
||||||
|
fn bar() -> void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> void {
|
fn main() -> void {
|
||||||
var a : vec2<f32> = vec2<f32>();
|
var a : vec2<f32> = vec2<f32>();
|
||||||
gl_FragColor = vec4<f32>(0.4, 0.4, 0.8, 1.0);
|
gl_FragColor = vec4<f32>(0.4, 0.4, 0.8, 1.0);
|
||||||
|
bar();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entry_point fragment = main;
|
entry_point fragment = main;
|
||||||
|
|
Loading…
Reference in New Issue