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:
dan sinclair 2020-07-21 15:13:36 +00:00 committed by dan sinclair
parent e5228407f4
commit fbbc617888
6 changed files with 145 additions and 0 deletions

View File

@ -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_body_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_const_expr_test.cc",
"src/reader/wgsl/parser_impl_const_literal_test.cc",

View File

@ -385,6 +385,7 @@ if(${TINT_BUILD_WGSL_READER})
reader/wgsl/parser_impl_assignment_stmt_test.cc
reader/wgsl/parser_impl_body_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_const_expr_test.cc
reader/wgsl/parser_impl_const_literal_test.cc

View File

@ -1422,6 +1422,7 @@ ast::StatementList ParserImpl::statements() {
// | if_stmt
// | switch_stmt
// | loop_stmt
// | func_call_stmt SEMICOLON
// | variable_stmt SEMICOLON
// | break_stmt SEMICOLON
// | continue_stmt SEMICOLON
@ -1464,6 +1465,18 @@ std::unique_ptr<ast::Statement> ParserImpl::statement() {
if (loop != nullptr)
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();
if (has_error())
return nullptr;
@ -1908,6 +1921,41 @@ std::unique_ptr<ast::LoopStatement> ParserImpl::loop_stmt() {
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
std::unique_ptr<ast::BreakStatement> ParserImpl::break_stmt() {

View File

@ -23,6 +23,7 @@
#include "src/ast/assignment_statement.h"
#include "src/ast/builtin.h"
#include "src/ast/call_statement.h"
#include "src/ast/case_statement.h"
#include "src/ast/constructor_expression.h"
#include "src/ast/else_statement.h"
@ -219,6 +220,9 @@ class ParserImpl {
/// Parses a `case_body` grammar element
/// @returns the parsed statements
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
/// @returns the parsed loop or nullptr
std::unique_ptr<ast::LoopStatement> loop_stmt();

View File

@ -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

View File

@ -14,9 +14,14 @@
[[location 0]] var<out> gl_FragColor : vec4<f32>;
fn bar() -> void {
}
fn main() -> void {
var a : vec2<f32> = vec2<f32>();
gl_FragColor = vec4<f32>(0.4, 0.4, 0.8, 1.0);
bar();
return;
}
entry_point fragment = main;