reader/wgsl: match spec rules for function calls
Function calls should be parsed in `primary_expression`. Renames the
old `postfix_expression` to `singular_expression`, with the recursive
part now becoming `postfix_expression`.
Fixed: tint:170
Change-Id: I1afad794880916db38a25d73447cdaf84abd6584
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49464
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Auto-Submit: James Price <jrprice@google.com>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 658f7dd..dbb4681 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -675,12 +675,12 @@
reader/wgsl/parser_impl_param_list_test.cc
reader/wgsl/parser_impl_paren_rhs_stmt_test.cc
reader/wgsl/parser_impl_pipeline_stage_test.cc
- reader/wgsl/parser_impl_postfix_expression_test.cc
reader/wgsl/parser_impl_primary_expression_test.cc
reader/wgsl/parser_impl_relational_expression_test.cc
reader/wgsl/parser_impl_sampled_texture_type_test.cc
reader/wgsl/parser_impl_sampler_type_test.cc
reader/wgsl/parser_impl_shift_expression_test.cc
+ reader/wgsl/parser_impl_singular_expression_test.cc
reader/wgsl/parser_impl_statement_test.cc
reader/wgsl/parser_impl_statements_test.cc
reader/wgsl/parser_impl_storage_class_test.cc
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index f643a21..7bbad45 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -2196,7 +2196,7 @@
}
// primary_expression
-// : IDENT
+// : IDENT argument_expression_list?
// | type_decl PAREN_LEFT argument_expression_list* PAREN_RIGHT
// | const_literal
// | paren_rhs_stmt
@@ -2235,8 +2235,30 @@
if (t.IsIdentifier() && !get_constructed(t.to_str())) {
next();
- return create<ast::IdentifierExpression>(
+
+ auto* ident = create<ast::IdentifierExpression>(
t.source(), builder_.Symbols().Register(t.to_str()));
+
+ if (match(Token::Type::kParenLeft, &source)) {
+ return sync(Token::Type::kParenRight, [&]() -> Maybe<ast::Expression*> {
+ ast::ExpressionList params;
+
+ auto t2 = peek();
+ if (!t2.IsParenRight() && !t2.IsEof()) {
+ auto list = expect_argument_expression_list();
+ if (list.errored)
+ return Failure::kErrored;
+ params = list.value;
+ }
+
+ if (!expect("call expression", Token::Type::kParenRight))
+ return Failure::kErrored;
+
+ return create<ast::CallExpression>(source, ident, params);
+ });
+ }
+
+ return ident;
}
auto type = type_decl();
@@ -2267,12 +2289,12 @@
return Failure::kNoMatch;
}
-// postfix_expr
+// postfix_expression
// :
// | BRACE_LEFT logical_or_expression BRACE_RIGHT postfix_expr
-// | PAREN_LEFT argument_expression_list* PAREN_RIGHT postfix_expr
// | PERIOD IDENTIFIER postfix_expr
-Maybe<ast::Expression*> ParserImpl::postfix_expr(ast::Expression* prefix) {
+Maybe<ast::Expression*> ParserImpl::postfix_expression(
+ ast::Expression* prefix) {
Source source;
if (match(Token::Type::kBracketLeft, &source)) {
return sync(Token::Type::kBracketRight, [&]() -> Maybe<ast::Expression*> {
@@ -2285,36 +2307,17 @@
if (!expect("array accessor", Token::Type::kBracketRight))
return Failure::kErrored;
- return postfix_expr(
+ return postfix_expression(
create<ast::ArrayAccessorExpression>(source, prefix, param.value));
});
}
- if (match(Token::Type::kParenLeft, &source)) {
- return sync(Token::Type::kParenRight, [&]() -> Maybe<ast::Expression*> {
- ast::ExpressionList params;
-
- auto t = peek();
- if (!t.IsParenRight() && !t.IsEof()) {
- auto list = expect_argument_expression_list();
- if (list.errored)
- return Failure::kErrored;
- params = list.value;
- }
-
- if (!expect("call expression", Token::Type::kParenRight))
- return Failure::kErrored;
-
- return postfix_expr(create<ast::CallExpression>(source, prefix, params));
- });
- }
-
if (match(Token::Type::kPeriod)) {
auto ident = expect_ident("member accessor");
if (ident.errored)
return Failure::kErrored;
- return postfix_expr(create<ast::MemberAccessorExpression>(
+ return postfix_expression(create<ast::MemberAccessorExpression>(
ident.source, prefix,
create<ast::IdentifierExpression>(
ident.source, builder_.Symbols().Register(ident.value))));
@@ -2323,16 +2326,16 @@
return prefix;
}
-// postfix_expression
+// singular_expression
// : primary_expression postfix_expr
-Maybe<ast::Expression*> ParserImpl::postfix_expression() {
+Maybe<ast::Expression*> ParserImpl::singular_expression() {
auto prefix = primary_expression();
if (prefix.errored)
return Failure::kErrored;
if (!prefix.matched)
return Failure::kNoMatch;
- return postfix_expr(prefix.value);
+ return postfix_expression(prefix.value);
}
// argument_expression_list
@@ -2361,7 +2364,7 @@
}
// unary_expression
-// : postfix_expression
+// : singular_expression
// | MINUS unary_expression
// | BANG unary_expression
Maybe<ast::Expression*> ParserImpl::unary_expression() {
@@ -2385,7 +2388,7 @@
return create<ast::UnaryOpExpression>(source, op, expr.value);
}
- return postfix_expression();
+ return singular_expression();
}
// multiplicative_expr
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index e01cf25..49a2d26 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -557,10 +557,10 @@
/// Parses the recursive portion of the postfix_expression
/// @param prefix the left side of the expression
/// @returns the parsed expression or nullptr
- Maybe<ast::Expression*> postfix_expr(ast::Expression* prefix);
- /// Parses a `postfix_expression` grammar elment
+ Maybe<ast::Expression*> postfix_expression(ast::Expression* prefix);
+ /// Parses a `singular_expression` grammar elment
/// @returns the parsed expression or nullptr
- Maybe<ast::Expression*> postfix_expression();
+ Maybe<ast::Expression*> singular_expression();
/// Parses a `unary_expression` grammar element
/// @returns the parsed expression or nullptr
Maybe<ast::Expression*> unary_expression();
diff --git a/src/reader/wgsl/parser_impl_postfix_expression_test.cc b/src/reader/wgsl/parser_impl_singular_expression_test.cc
similarity index 81%
rename from src/reader/wgsl/parser_impl_postfix_expression_test.cc
rename to src/reader/wgsl/parser_impl_singular_expression_test.cc
index 0b6eafa..30e2067 100644
--- a/src/reader/wgsl/parser_impl_postfix_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_singular_expression_test.cc
@@ -19,9 +19,9 @@
namespace wgsl {
namespace {
-TEST_F(ParserImplTest, PostfixExpression_Array_ConstantIndex) {
+TEST_F(ParserImplTest, SingularExpression_Array_ConstantIndex) {
auto p = parser("a[1]");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -41,9 +41,9 @@
EXPECT_EQ(c->literal()->As<ast::SintLiteral>()->value(), 1);
}
-TEST_F(ParserImplTest, PostfixExpression_Array_ExpressionIndex) {
+TEST_F(ParserImplTest, SingularExpression_Array_ExpressionIndex) {
auto p = parser("a[1 + b / 4]");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -59,9 +59,9 @@
ASSERT_TRUE(ary->idx_expr()->Is<ast::BinaryExpression>());
}
-TEST_F(ParserImplTest, PostfixExpression_Array_MissingIndex) {
+TEST_F(ParserImplTest, SingularExpression_Array_MissingIndex) {
auto p = parser("a[]");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -69,9 +69,9 @@
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
}
-TEST_F(ParserImplTest, PostfixExpression_Array_MissingRightBrace) {
+TEST_F(ParserImplTest, SingularExpression_Array_MissingRightBrace) {
auto p = parser("a[1");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -79,9 +79,9 @@
EXPECT_EQ(p->error(), "1:4: expected ']' for array accessor");
}
-TEST_F(ParserImplTest, PostfixExpression_Array_InvalidIndex) {
+TEST_F(ParserImplTest, SingularExpression_Array_InvalidIndex) {
auto p = parser("a[if(a() {})]");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -89,9 +89,9 @@
EXPECT_EQ(p->error(), "1:3: unable to parse expression inside []");
}
-TEST_F(ParserImplTest, PostfixExpression_Call_Empty) {
+TEST_F(ParserImplTest, SingularExpression_Call_Empty) {
auto p = parser("a()");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -107,9 +107,9 @@
EXPECT_EQ(c->params().size(), 0u);
}
-TEST_F(ParserImplTest, PostfixExpression_Call_WithArgs) {
+TEST_F(ParserImplTest, SingularExpression_Call_WithArgs) {
auto p = parser("test(1, b, 2 + 3 / b)");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -128,9 +128,9 @@
EXPECT_TRUE(c->params()[2]->Is<ast::BinaryExpression>());
}
-TEST_F(ParserImplTest, PostfixExpression_Call_InvalidArg) {
+TEST_F(ParserImplTest, SingularExpression_Call_InvalidArg) {
auto p = parser("a(if(a) {})");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -138,9 +138,9 @@
EXPECT_EQ(p->error(), "1:3: unable to parse argument expression");
}
-TEST_F(ParserImplTest, PostfixExpression_Call_HangingComma) {
+TEST_F(ParserImplTest, SingularExpression_Call_HangingComma) {
auto p = parser("a(b, )");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -148,9 +148,9 @@
EXPECT_EQ(p->error(), "1:6: unable to parse argument expression after comma");
}
-TEST_F(ParserImplTest, PostfixExpression_Call_MissingRightParen) {
+TEST_F(ParserImplTest, SingularExpression_Call_MissingRightParen) {
auto p = parser("a(");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -158,9 +158,9 @@
EXPECT_EQ(p->error(), "1:3: expected ')' for call expression");
}
-TEST_F(ParserImplTest, PostfixExpression_MemberAccessor) {
+TEST_F(ParserImplTest, SingularExpression_MemberAccessor) {
auto p = parser("a.b");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -177,9 +177,9 @@
p->builder().Symbols().Get("b"));
}
-TEST_F(ParserImplTest, PostfixExpression_MemberAccesssor_InvalidIdent) {
+TEST_F(ParserImplTest, SingularExpression_MemberAccesssor_InvalidIdent) {
auto p = parser("a.if");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -187,9 +187,9 @@
EXPECT_EQ(p->error(), "1:3: expected identifier for member accessor");
}
-TEST_F(ParserImplTest, PostfixExpression_MemberAccessor_MissingIdent) {
+TEST_F(ParserImplTest, SingularExpression_MemberAccessor_MissingIdent) {
auto p = parser("a.");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
@@ -197,9 +197,9 @@
EXPECT_EQ(p->error(), "1:3: expected identifier for member accessor");
}
-TEST_F(ParserImplTest, PostfixExpression_NonMatch_returnLHS) {
+TEST_F(ParserImplTest, SingularExpression_NonMatch_returnLHS) {
auto p = parser("a b");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
@@ -207,9 +207,9 @@
ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
}
-TEST_F(ParserImplTest, PostfixExpression_Array_NestedArrayAccessor) {
+TEST_F(ParserImplTest, SingularExpression_Array_NestedArrayAccessor) {
auto p = parser("a[b[c]]");
- auto e = p->postfix_expression();
+ auto e = p->singular_expression();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 30ace0e..cd3e013 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -438,12 +438,12 @@
"../src/reader/wgsl/parser_impl_param_list_test.cc",
"../src/reader/wgsl/parser_impl_paren_rhs_stmt_test.cc",
"../src/reader/wgsl/parser_impl_pipeline_stage_test.cc",
- "../src/reader/wgsl/parser_impl_postfix_expression_test.cc",
"../src/reader/wgsl/parser_impl_primary_expression_test.cc",
"../src/reader/wgsl/parser_impl_relational_expression_test.cc",
"../src/reader/wgsl/parser_impl_sampled_texture_type_test.cc",
"../src/reader/wgsl/parser_impl_sampler_type_test.cc",
"../src/reader/wgsl/parser_impl_shift_expression_test.cc",
+ "../src/reader/wgsl/parser_impl_singular_expression_test.cc",
"../src/reader/wgsl/parser_impl_statement_test.cc",
"../src/reader/wgsl/parser_impl_statements_test.cc",
"../src/reader/wgsl/parser_impl_storage_class_test.cc",