1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/reader/wgsl/parser_impl_test_helper.h"
16
17 namespace tint {
18 namespace reader {
19 namespace wgsl {
20 namespace {
21
TEST_F(ParserImplTest,ConstExpr_TypeDecl)22 TEST_F(ParserImplTest, ConstExpr_TypeDecl) {
23 auto p = parser("vec2<f32>(1., 2.)");
24 auto e = p->expect_const_expr();
25 ASSERT_FALSE(p->has_error()) << p->error();
26 ASSERT_FALSE(e.errored);
27 ASSERT_TRUE(e->Is<ast::CallExpression>());
28
29 auto* t = e->As<ast::CallExpression>();
30 ASSERT_TRUE(t->target.type->Is<ast::Vector>());
31 EXPECT_EQ(t->target.type->As<ast::Vector>()->width, 2u);
32
33 ASSERT_EQ(t->args.size(), 2u);
34
35 ASSERT_TRUE(t->args[0]->Is<ast::FloatLiteralExpression>());
36 EXPECT_FLOAT_EQ(t->args[0]->As<ast::FloatLiteralExpression>()->value, 1.);
37
38 ASSERT_TRUE(t->args[1]->Is<ast::FloatLiteralExpression>());
39 EXPECT_FLOAT_EQ(t->args[1]->As<ast::FloatLiteralExpression>()->value, 2.);
40 }
41
TEST_F(ParserImplTest,ConstExpr_TypeDecl_Empty)42 TEST_F(ParserImplTest, ConstExpr_TypeDecl_Empty) {
43 auto p = parser("vec2<f32>()");
44 auto e = p->expect_const_expr();
45 ASSERT_FALSE(p->has_error()) << p->error();
46 ASSERT_FALSE(e.errored);
47 ASSERT_TRUE(e->Is<ast::CallExpression>());
48
49 auto* t = e->As<ast::CallExpression>();
50 ASSERT_TRUE(t->target.type->Is<ast::Vector>());
51 EXPECT_EQ(t->target.type->As<ast::Vector>()->width, 2u);
52
53 ASSERT_EQ(t->args.size(), 0u);
54 }
55
TEST_F(ParserImplTest,ConstExpr_TypeDecl_TrailingComma)56 TEST_F(ParserImplTest, ConstExpr_TypeDecl_TrailingComma) {
57 auto p = parser("vec2<f32>(1., 2.,)");
58 auto e = p->expect_const_expr();
59 ASSERT_FALSE(p->has_error()) << p->error();
60 ASSERT_FALSE(e.errored);
61 ASSERT_TRUE(e->Is<ast::CallExpression>());
62
63 auto* t = e->As<ast::CallExpression>();
64 ASSERT_TRUE(t->target.type->Is<ast::Vector>());
65 EXPECT_EQ(t->target.type->As<ast::Vector>()->width, 2u);
66
67 ASSERT_EQ(t->args.size(), 2u);
68 ASSERT_TRUE(t->args[0]->Is<ast::LiteralExpression>());
69 ASSERT_TRUE(t->args[1]->Is<ast::LiteralExpression>());
70 }
71
TEST_F(ParserImplTest,ConstExpr_TypeDecl_MissingRightParen)72 TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingRightParen) {
73 auto p = parser("vec2<f32>(1., 2.");
74 auto e = p->expect_const_expr();
75 ASSERT_TRUE(p->has_error());
76 ASSERT_TRUE(e.errored);
77 ASSERT_EQ(e.value, nullptr);
78 EXPECT_EQ(p->error(), "1:17: expected ')' for type constructor");
79 }
80
TEST_F(ParserImplTest,ConstExpr_TypeDecl_MissingLeftParen)81 TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingLeftParen) {
82 auto p = parser("vec2<f32> 1., 2.)");
83 auto e = p->expect_const_expr();
84 ASSERT_TRUE(p->has_error());
85 ASSERT_TRUE(e.errored);
86 ASSERT_EQ(e.value, nullptr);
87 EXPECT_EQ(p->error(), "1:11: expected '(' for type constructor");
88 }
89
TEST_F(ParserImplTest,ConstExpr_TypeDecl_MissingComma)90 TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingComma) {
91 auto p = parser("vec2<f32>(1. 2.");
92 auto e = p->expect_const_expr();
93 ASSERT_TRUE(p->has_error());
94 ASSERT_TRUE(e.errored);
95 ASSERT_EQ(e.value, nullptr);
96 EXPECT_EQ(p->error(), "1:14: expected ')' for type constructor");
97 }
98
TEST_F(ParserImplTest,ConstExpr_InvalidExpr)99 TEST_F(ParserImplTest, ConstExpr_InvalidExpr) {
100 auto p = parser("vec2<f32>(1., if(a) {})");
101 auto e = p->expect_const_expr();
102 ASSERT_TRUE(p->has_error());
103 ASSERT_TRUE(e.errored);
104 ASSERT_EQ(e.value, nullptr);
105 EXPECT_EQ(p->error(), "1:15: invalid type for const_expr");
106 }
107
TEST_F(ParserImplTest,ConstExpr_ConstLiteral)108 TEST_F(ParserImplTest, ConstExpr_ConstLiteral) {
109 auto p = parser("true");
110 auto e = p->expect_const_expr();
111 ASSERT_FALSE(p->has_error()) << p->error();
112 ASSERT_FALSE(e.errored);
113 ASSERT_NE(e.value, nullptr);
114 ASSERT_TRUE(e.value->Is<ast::BoolLiteralExpression>());
115 EXPECT_TRUE(e.value->As<ast::BoolLiteralExpression>()->value);
116 }
117
TEST_F(ParserImplTest,ConstExpr_ConstLiteral_Invalid)118 TEST_F(ParserImplTest, ConstExpr_ConstLiteral_Invalid) {
119 auto p = parser("invalid");
120 auto e = p->expect_const_expr();
121 ASSERT_TRUE(p->has_error());
122 ASSERT_TRUE(e.errored);
123 ASSERT_EQ(e.value, nullptr);
124 EXPECT_EQ(p->error(), "1:1: unable to parse const_expr");
125 }
126
TEST_F(ParserImplTest,ConstExpr_TypeConstructor)127 TEST_F(ParserImplTest, ConstExpr_TypeConstructor) {
128 auto p = parser("S(0)");
129
130 auto e = p->expect_const_expr();
131 ASSERT_FALSE(e.errored);
132 ASSERT_TRUE(e->Is<ast::CallExpression>());
133 ASSERT_NE(e->As<ast::CallExpression>()->target.type, nullptr);
134 ASSERT_TRUE(e->As<ast::CallExpression>()->target.type->Is<ast::TypeName>());
135 EXPECT_EQ(
136 e->As<ast::CallExpression>()->target.type->As<ast::TypeName>()->name,
137 p->builder().Symbols().Get("S"));
138 }
139
TEST_F(ParserImplTest,ConstExpr_Recursion)140 TEST_F(ParserImplTest, ConstExpr_Recursion) {
141 std::stringstream out;
142 for (size_t i = 0; i < 200; i++) {
143 out << "f32(";
144 }
145 out << "1.0";
146 for (size_t i = 0; i < 200; i++) {
147 out << ")";
148 }
149 auto p = parser(out.str());
150 auto e = p->expect_const_expr();
151 ASSERT_TRUE(p->has_error());
152 ASSERT_TRUE(e.errored);
153 ASSERT_EQ(e.value, nullptr);
154 EXPECT_EQ(p->error(), "1:517: maximum parser recursive depth reached");
155 }
156
TEST_F(ParserImplTest,UnaryOp_Recursion)157 TEST_F(ParserImplTest, UnaryOp_Recursion) {
158 std::stringstream out;
159 for (size_t i = 0; i < 200; i++) {
160 out << "!";
161 }
162 out << "1.0";
163 auto p = parser(out.str());
164 auto e = p->unary_expression();
165 ASSERT_TRUE(p->has_error());
166 ASSERT_TRUE(e.errored);
167 ASSERT_EQ(e.value, nullptr);
168 EXPECT_EQ(p->error(), "1:130: maximum parser recursive depth reached");
169 }
170
171 } // namespace
172 } // namespace wgsl
173 } // namespace reader
174 } // namespace tint
175