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/ast/break_statement.h"
16 #include "src/ast/continue_statement.h"
17 #include "src/ast/discard_statement.h"
18 #include "src/reader/wgsl/parser_impl_test_helper.h"
19
20 namespace tint {
21 namespace reader {
22 namespace wgsl {
23 namespace {
24
TEST_F(ParserImplTest,Statement)25 TEST_F(ParserImplTest, Statement) {
26 auto p = parser("return;");
27 auto e = p->statement();
28 ASSERT_FALSE(p->has_error()) << p->error();
29 EXPECT_TRUE(e.matched);
30 EXPECT_FALSE(e.errored);
31 ASSERT_TRUE(e->Is<ast::ReturnStatement>());
32 }
33
TEST_F(ParserImplTest,Statement_Semicolon)34 TEST_F(ParserImplTest, Statement_Semicolon) {
35 auto p = parser(";");
36 p->statement();
37 ASSERT_FALSE(p->has_error()) << p->error();
38 }
39
TEST_F(ParserImplTest,Statement_Return_NoValue)40 TEST_F(ParserImplTest, Statement_Return_NoValue) {
41 auto p = parser("return;");
42 auto e = p->statement();
43 ASSERT_FALSE(p->has_error()) << p->error();
44 EXPECT_TRUE(e.matched);
45 EXPECT_FALSE(e.errored);
46 ASSERT_TRUE(e->Is<ast::ReturnStatement>());
47 auto* ret = e->As<ast::ReturnStatement>();
48 ASSERT_EQ(ret->value, nullptr);
49 }
50
TEST_F(ParserImplTest,Statement_Return_Value)51 TEST_F(ParserImplTest, Statement_Return_Value) {
52 auto p = parser("return a + b * (.1 - .2);");
53 auto e = p->statement();
54 ASSERT_FALSE(p->has_error()) << p->error();
55
56 EXPECT_TRUE(e.matched);
57 EXPECT_FALSE(e.errored);
58 ASSERT_TRUE(e->Is<ast::ReturnStatement>());
59 auto* ret = e->As<ast::ReturnStatement>();
60 ASSERT_NE(ret->value, nullptr);
61 EXPECT_TRUE(ret->value->Is<ast::BinaryExpression>());
62 }
63
TEST_F(ParserImplTest,Statement_Return_MissingSemi)64 TEST_F(ParserImplTest, Statement_Return_MissingSemi) {
65 auto p = parser("return");
66 auto e = p->statement();
67 EXPECT_TRUE(p->has_error());
68 EXPECT_TRUE(e.errored);
69 EXPECT_FALSE(e.matched);
70 EXPECT_EQ(e.value, nullptr);
71 EXPECT_EQ(p->error(), "1:7: expected ';' for return statement");
72 }
73
TEST_F(ParserImplTest,Statement_Return_Invalid)74 TEST_F(ParserImplTest, Statement_Return_Invalid) {
75 auto p = parser("return if(a) {};");
76 auto e = p->statement();
77 EXPECT_TRUE(p->has_error());
78 EXPECT_TRUE(e.errored);
79 EXPECT_FALSE(e.matched);
80 EXPECT_EQ(e.value, nullptr);
81 EXPECT_EQ(p->error(), "1:8: expected ';' for return statement");
82 }
83
TEST_F(ParserImplTest,Statement_If)84 TEST_F(ParserImplTest, Statement_If) {
85 auto p = parser("if (a) {}");
86 auto e = p->statement();
87 ASSERT_FALSE(p->has_error()) << p->error();
88 EXPECT_TRUE(e.matched);
89 EXPECT_FALSE(e.errored);
90 ASSERT_TRUE(e->Is<ast::IfStatement>());
91 }
92
TEST_F(ParserImplTest,Statement_If_Invalid)93 TEST_F(ParserImplTest, Statement_If_Invalid) {
94 auto p = parser("if (a) { fn main() -> {}}");
95 auto e = p->statement();
96 EXPECT_TRUE(p->has_error());
97 EXPECT_TRUE(e.errored);
98 EXPECT_FALSE(e.matched);
99 EXPECT_EQ(e.value, nullptr);
100 EXPECT_EQ(p->error(), "1:10: expected '}'");
101 }
102
TEST_F(ParserImplTest,Statement_Variable)103 TEST_F(ParserImplTest, Statement_Variable) {
104 auto p = parser("var a : i32 = 1;");
105 auto e = p->statement();
106 ASSERT_FALSE(p->has_error()) << p->error();
107 EXPECT_TRUE(e.matched);
108 EXPECT_FALSE(e.errored);
109 ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
110 }
111
TEST_F(ParserImplTest,Statement_Variable_Invalid)112 TEST_F(ParserImplTest, Statement_Variable_Invalid) {
113 auto p = parser("var a : i32 =;");
114 auto e = p->statement();
115 EXPECT_TRUE(p->has_error());
116 EXPECT_TRUE(e.errored);
117 EXPECT_FALSE(e.matched);
118 EXPECT_EQ(e.value, nullptr);
119 EXPECT_EQ(p->error(), "1:14: missing constructor for variable declaration");
120 }
121
TEST_F(ParserImplTest,Statement_Variable_MissingSemicolon)122 TEST_F(ParserImplTest, Statement_Variable_MissingSemicolon) {
123 auto p = parser("var a : i32");
124 auto e = p->statement();
125 EXPECT_TRUE(p->has_error());
126 EXPECT_TRUE(e.errored);
127 EXPECT_FALSE(e.matched);
128 EXPECT_EQ(e.value, nullptr);
129 EXPECT_EQ(p->error(), "1:12: expected ';' for variable declaration");
130 }
131
TEST_F(ParserImplTest,Statement_Switch)132 TEST_F(ParserImplTest, Statement_Switch) {
133 auto p = parser("switch (a) {}");
134 auto e = p->statement();
135 ASSERT_FALSE(p->has_error()) << p->error();
136 EXPECT_TRUE(e.matched);
137 EXPECT_FALSE(e.errored);
138 ASSERT_TRUE(e->Is<ast::SwitchStatement>());
139 }
140
TEST_F(ParserImplTest,Statement_Switch_Invalid)141 TEST_F(ParserImplTest, Statement_Switch_Invalid) {
142 auto p = parser("switch (a) { case: {}}");
143 auto e = p->statement();
144 EXPECT_TRUE(p->has_error());
145 EXPECT_TRUE(e.errored);
146 EXPECT_FALSE(e.matched);
147 EXPECT_EQ(e.value, nullptr);
148 EXPECT_EQ(p->error(), "1:18: unable to parse case selectors");
149 }
150
TEST_F(ParserImplTest,Statement_Loop)151 TEST_F(ParserImplTest, Statement_Loop) {
152 auto p = parser("loop {}");
153 auto e = p->statement();
154 ASSERT_FALSE(p->has_error()) << p->error();
155 EXPECT_TRUE(e.matched);
156 EXPECT_FALSE(e.errored);
157 ASSERT_TRUE(e->Is<ast::LoopStatement>());
158 }
159
TEST_F(ParserImplTest,Statement_Loop_Invalid)160 TEST_F(ParserImplTest, Statement_Loop_Invalid) {
161 auto p = parser("loop discard; }");
162 auto e = p->statement();
163 EXPECT_TRUE(p->has_error());
164 EXPECT_TRUE(e.errored);
165 EXPECT_FALSE(e.matched);
166 EXPECT_EQ(e.value, nullptr);
167 EXPECT_EQ(p->error(), "1:6: expected '{' for loop");
168 }
169
TEST_F(ParserImplTest,Statement_Assignment)170 TEST_F(ParserImplTest, Statement_Assignment) {
171 auto p = parser("a = b;");
172 auto e = p->statement();
173 ASSERT_FALSE(p->has_error()) << p->error();
174 EXPECT_TRUE(e.matched);
175 EXPECT_FALSE(e.errored);
176 ASSERT_TRUE(e->Is<ast::AssignmentStatement>());
177 }
178
TEST_F(ParserImplTest,Statement_Assignment_Invalid)179 TEST_F(ParserImplTest, Statement_Assignment_Invalid) {
180 auto p = parser("a = if(b) {};");
181 auto e = p->statement();
182 EXPECT_TRUE(p->has_error());
183 EXPECT_TRUE(e.errored);
184 EXPECT_FALSE(e.matched);
185 EXPECT_EQ(e.value, nullptr);
186 EXPECT_EQ(p->error(), "1:5: unable to parse right side of assignment");
187 }
188
TEST_F(ParserImplTest,Statement_Assignment_MissingSemicolon)189 TEST_F(ParserImplTest, Statement_Assignment_MissingSemicolon) {
190 auto p = parser("a = b");
191 auto e = p->statement();
192 EXPECT_TRUE(p->has_error());
193 EXPECT_TRUE(e.errored);
194 EXPECT_FALSE(e.matched);
195 EXPECT_EQ(e.value, nullptr);
196 EXPECT_EQ(p->error(), "1:6: expected ';' for assignment statement");
197 }
198
TEST_F(ParserImplTest,Statement_Break)199 TEST_F(ParserImplTest, Statement_Break) {
200 auto p = parser("break;");
201 auto e = p->statement();
202 ASSERT_FALSE(p->has_error()) << p->error();
203 EXPECT_TRUE(e.matched);
204 EXPECT_FALSE(e.errored);
205 ASSERT_TRUE(e->Is<ast::BreakStatement>());
206 }
207
TEST_F(ParserImplTest,Statement_Break_MissingSemicolon)208 TEST_F(ParserImplTest, Statement_Break_MissingSemicolon) {
209 auto p = parser("break");
210 auto e = p->statement();
211 EXPECT_TRUE(p->has_error());
212 EXPECT_TRUE(e.errored);
213 EXPECT_FALSE(e.matched);
214 EXPECT_EQ(e.value, nullptr);
215 EXPECT_EQ(p->error(), "1:6: expected ';' for break statement");
216 }
217
TEST_F(ParserImplTest,Statement_Continue)218 TEST_F(ParserImplTest, Statement_Continue) {
219 auto p = parser("continue;");
220 auto e = p->statement();
221 ASSERT_FALSE(p->has_error()) << p->error();
222 EXPECT_TRUE(e.matched);
223 EXPECT_FALSE(e.errored);
224 ASSERT_TRUE(e->Is<ast::ContinueStatement>());
225 }
226
TEST_F(ParserImplTest,Statement_Continue_MissingSemicolon)227 TEST_F(ParserImplTest, Statement_Continue_MissingSemicolon) {
228 auto p = parser("continue");
229 auto e = p->statement();
230 EXPECT_TRUE(p->has_error());
231 EXPECT_TRUE(e.errored);
232 EXPECT_FALSE(e.matched);
233 EXPECT_EQ(e.value, nullptr);
234 EXPECT_EQ(p->error(), "1:9: expected ';' for continue statement");
235 }
236
TEST_F(ParserImplTest,Statement_Discard)237 TEST_F(ParserImplTest, Statement_Discard) {
238 auto p = parser("discard;");
239 auto e = p->statement();
240 ASSERT_FALSE(p->has_error()) << p->error();
241 ASSERT_NE(e.value, nullptr);
242 EXPECT_TRUE(e.matched);
243 EXPECT_FALSE(e.errored);
244 ASSERT_TRUE(e->Is<ast::DiscardStatement>());
245 }
246
TEST_F(ParserImplTest,Statement_Discard_MissingSemicolon)247 TEST_F(ParserImplTest, Statement_Discard_MissingSemicolon) {
248 auto p = parser("discard");
249 auto e = p->statement();
250 EXPECT_TRUE(p->has_error());
251 EXPECT_EQ(e.value, nullptr);
252 EXPECT_TRUE(e.errored);
253 EXPECT_FALSE(e.matched);
254 EXPECT_EQ(p->error(), "1:8: expected ';' for discard statement");
255 }
256
TEST_F(ParserImplTest,Statement_Body)257 TEST_F(ParserImplTest, Statement_Body) {
258 auto p = parser("{ var i: i32; }");
259 auto e = p->statement();
260 ASSERT_FALSE(p->has_error()) << p->error();
261 EXPECT_TRUE(e.matched);
262 EXPECT_FALSE(e.errored);
263 ASSERT_TRUE(e->Is<ast::BlockStatement>());
264 EXPECT_TRUE(e->As<ast::BlockStatement>()
265 ->statements[0]
266 ->Is<ast::VariableDeclStatement>());
267 }
268
TEST_F(ParserImplTest,Statement_Body_Invalid)269 TEST_F(ParserImplTest, Statement_Body_Invalid) {
270 auto p = parser("{ fn main() -> {}}");
271 auto e = p->statement();
272 EXPECT_TRUE(p->has_error());
273 EXPECT_TRUE(e.errored);
274 EXPECT_FALSE(e.matched);
275 EXPECT_EQ(e.value, nullptr);
276 EXPECT_EQ(p->error(), "1:3: expected '}'");
277 }
278
279 } // namespace
280 } // namespace wgsl
281 } // namespace reader
282 } // namespace tint
283