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
22 const diag::Formatter::Style formatter_style{
23 /* print_file: */ true, /* print_severity: */ true,
24 /* print_line: */ true, /* print_newline_at_end: */ false};
25
26 class ParserImplErrorResyncTest : public ParserImplTest {};
27
28 #define EXPECT(SOURCE, EXPECTED) \
29 do { \
30 std::string source = SOURCE; \
31 std::string expected = EXPECTED; \
32 auto p = parser(source); \
33 EXPECT_EQ(false, p->Parse()); \
34 auto diagnostics = p->builder().Diagnostics(); \
35 EXPECT_EQ(true, diagnostics.contains_errors()); \
36 EXPECT_EQ(expected, diag::Formatter(formatter_style).format(diagnostics)); \
37 } while (false)
38
TEST_F(ParserImplErrorResyncTest,BadFunctionDecls)39 TEST_F(ParserImplErrorResyncTest, BadFunctionDecls) {
40 EXPECT(R"(
41 fn .() -> . {}
42 fn x(.) {}
43 [[.,.]] fn -> {}
44 fn good() {}
45 )",
46 "test.wgsl:2:4 error: expected identifier for function declaration\n"
47 "fn .() -> . {}\n"
48 " ^\n"
49 "\n"
50 "test.wgsl:2:11 error: unable to determine function return type\n"
51 "fn .() -> . {}\n"
52 " ^\n"
53 "\n"
54 "test.wgsl:3:6 error: expected ')' for function declaration\n"
55 "fn x(.) {}\n"
56 " ^\n"
57 "\n"
58 "test.wgsl:4:3 error: expected decoration\n"
59 "[[.,.]] fn -> {}\n"
60 " ^\n"
61 "\n"
62 "test.wgsl:4:5 error: expected decoration\n"
63 "[[.,.]] fn -> {}\n"
64 " ^\n"
65 "\n"
66 "test.wgsl:4:12 error: expected identifier for function declaration\n"
67 "[[.,.]] fn -> {}\n"
68 " ^^\n");
69 }
70
TEST_F(ParserImplErrorResyncTest,AssignmentStatement)71 TEST_F(ParserImplErrorResyncTest, AssignmentStatement) {
72 EXPECT(R"(
73 fn f() {
74 blah blah blah blah;
75 good = 1;
76 blah blah blah blah;
77 x = .;
78 good = 1;
79 }
80 )",
81 "test.wgsl:3:8 error: expected '=' for assignment\n"
82 " blah blah blah blah;\n"
83 " ^^^^\n"
84 "\n"
85 "test.wgsl:5:8 error: expected '=' for assignment\n"
86 " blah blah blah blah;\n"
87 " ^^^^\n"
88 "\n"
89 "test.wgsl:6:7 error: unable to parse right side of assignment\n"
90 " x = .;\n"
91 " ^\n");
92 }
93
TEST_F(ParserImplErrorResyncTest,DiscardStatement)94 TEST_F(ParserImplErrorResyncTest, DiscardStatement) {
95 EXPECT(R"(
96 fn f() {
97 discard blah blah blah;
98 a = 1;
99 discard blah blah blah;
100 }
101 )",
102 "test.wgsl:3:11 error: expected ';' for discard statement\n"
103 " discard blah blah blah;\n"
104 " ^^^^\n"
105 "\n"
106 "test.wgsl:5:11 error: expected ';' for discard statement\n"
107 " discard blah blah blah;\n"
108 " ^^^^\n");
109 }
110
TEST_F(ParserImplErrorResyncTest,StructMembers)111 TEST_F(ParserImplErrorResyncTest, StructMembers) {
112 EXPECT(R"(
113 struct S {
114 blah blah blah;
115 a : i32;
116 blah blah blah;
117 b : i32;
118 [[]] x : i32;
119 c : i32;
120 }
121 )",
122 "test.wgsl:3:10 error: expected ':' for struct member\n"
123 " blah blah blah;\n"
124 " ^^^^\n"
125 "\n"
126 "test.wgsl:5:10 error: expected ':' for struct member\n"
127 " blah blah blah;\n"
128 " ^^^^\n"
129 "\n"
130 "test.wgsl:7:7 error: empty decoration list\n"
131 " [[]] x : i32;\n"
132 " ^^\n");
133 }
134
135 // Check that the forward scan in resynchronize() stop at nested sync points.
136 // In this test the inner resynchronize() is looking for a terminating ';', and
137 // the outer resynchronize() is looking for a terminating '}' for the function
138 // scope.
TEST_F(ParserImplErrorResyncTest,NestedSyncPoints)139 TEST_F(ParserImplErrorResyncTest, NestedSyncPoints) {
140 EXPECT(R"(
141 fn f() {
142 x = 1;
143 discard
144 }
145 struct S { blah };
146 )",
147 "test.wgsl:5:1 error: expected ';' for discard statement\n"
148 "}\n"
149 "^\n"
150 "\n"
151 "test.wgsl:6:17 error: expected ':' for struct member\n"
152 "struct S { blah };\n"
153 " ^\n");
154 }
155
TEST_F(ParserImplErrorResyncTest,BracketCounting)156 TEST_F(ParserImplErrorResyncTest, BracketCounting) {
157 EXPECT(R"(
158 [[woof[[[[]]]]]]
159 fn f(x(((())))) {
160 meow = {{{}}}
161 }
162 struct S { blah };
163 )",
164 "test.wgsl:2:3 error: expected decoration\n"
165 "[[woof[[[[]]]]]]\n"
166 " ^^^^\n"
167 "\n"
168 "test.wgsl:3:7 error: expected ':' for parameter\n"
169 "fn f(x(((())))) {\n"
170 " ^\n"
171 "\n"
172 "test.wgsl:4:10 error: unable to parse right side of assignment\n"
173 " meow = {{{}}}\n"
174 " ^\n"
175 "\n"
176 "test.wgsl:6:17 error: expected ':' for struct member\n"
177 "struct S { blah };\n"
178 " ^\n");
179 }
180
181 } // namespace
182 } // namespace wgsl
183 } // namespace reader
184 } // namespace tint
185