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 #include <cmath>
18 #include <cstring>
19
20 namespace tint {
21 namespace reader {
22 namespace wgsl {
23 namespace {
24
25 // Makes an IEEE 754 binary32 floating point number with
26 // - 0 sign if sign is 0, 1 otherwise
27 // - 'exponent_bits' is placed in the exponent space.
28 // So, the exponent bias must already be included.
MakeFloat(int sign,int biased_exponent,int mantissa)29 float MakeFloat(int sign, int biased_exponent, int mantissa) {
30 const uint32_t sign_bit = sign ? 0x80000000u : 0u;
31 // The binary32 exponent is 8 bits, just below the sign.
32 const uint32_t exponent_bits = (biased_exponent & 0xffu) << 23;
33 // The mantissa is the bottom 23 bits.
34 const uint32_t mantissa_bits = (mantissa & 0x7fffffu);
35
36 uint32_t bits = sign_bit | exponent_bits | mantissa_bits;
37 float result = 0.0f;
38 static_assert(sizeof(result) == sizeof(bits),
39 "expected float and uint32_t to be the same size");
40 std::memcpy(&result, &bits, sizeof(bits));
41 return result;
42 }
43
TEST_F(ParserImplTest,ConstLiteral_Int)44 TEST_F(ParserImplTest, ConstLiteral_Int) {
45 auto p = parser("-234");
46 auto c = p->const_literal();
47 EXPECT_TRUE(c.matched);
48 EXPECT_FALSE(c.errored);
49 EXPECT_FALSE(p->has_error()) << p->error();
50 ASSERT_NE(c.value, nullptr);
51 ASSERT_TRUE(c->Is<ast::SintLiteralExpression>());
52 EXPECT_EQ(c->As<ast::SintLiteralExpression>()->value, -234);
53 EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
54 }
55
TEST_F(ParserImplTest,ConstLiteral_Uint)56 TEST_F(ParserImplTest, ConstLiteral_Uint) {
57 auto p = parser("234u");
58 auto c = p->const_literal();
59 EXPECT_TRUE(c.matched);
60 EXPECT_FALSE(c.errored);
61 EXPECT_FALSE(p->has_error()) << p->error();
62 ASSERT_NE(c.value, nullptr);
63 ASSERT_TRUE(c->Is<ast::UintLiteralExpression>());
64 EXPECT_EQ(c->As<ast::UintLiteralExpression>()->value, 234u);
65 EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
66 }
67
TEST_F(ParserImplTest,ConstLiteral_Float)68 TEST_F(ParserImplTest, ConstLiteral_Float) {
69 auto p = parser("234.e12");
70 auto c = p->const_literal();
71 EXPECT_TRUE(c.matched);
72 EXPECT_FALSE(c.errored);
73 EXPECT_FALSE(p->has_error()) << p->error();
74 ASSERT_NE(c.value, nullptr);
75 ASSERT_TRUE(c->Is<ast::FloatLiteralExpression>());
76 EXPECT_FLOAT_EQ(c->As<ast::FloatLiteralExpression>()->value, 234e12f);
77 EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 8u}}));
78 }
79
TEST_F(ParserImplTest,ConstLiteral_InvalidFloat_IncompleteExponent)80 TEST_F(ParserImplTest, ConstLiteral_InvalidFloat_IncompleteExponent) {
81 auto p = parser("1.0e+");
82 auto c = p->const_literal();
83 EXPECT_FALSE(c.matched);
84 EXPECT_TRUE(c.errored);
85 EXPECT_EQ(p->error(),
86 "1:1: incomplete exponent for floating point literal: 1.0e+");
87 ASSERT_EQ(c.value, nullptr);
88 }
89
TEST_F(ParserImplTest,ConstLiteral_InvalidFloat_TooSmallMagnitude)90 TEST_F(ParserImplTest, ConstLiteral_InvalidFloat_TooSmallMagnitude) {
91 auto p = parser("1e-256");
92 auto c = p->const_literal();
93 EXPECT_FALSE(c.matched);
94 EXPECT_TRUE(c.errored);
95 EXPECT_EQ(p->error(),
96 "1:1: f32 (1e-256) magnitude too small, not representable");
97 ASSERT_EQ(c.value, nullptr);
98 }
99
TEST_F(ParserImplTest,ConstLiteral_InvalidFloat_TooLargeNegative)100 TEST_F(ParserImplTest, ConstLiteral_InvalidFloat_TooLargeNegative) {
101 auto p = parser("-1.2e+256");
102 auto c = p->const_literal();
103 EXPECT_FALSE(c.matched);
104 EXPECT_TRUE(c.errored);
105 EXPECT_EQ(p->error(), "1:1: f32 (-1.2e+256) too large (negative)");
106 ASSERT_EQ(c.value, nullptr);
107 }
108
TEST_F(ParserImplTest,ConstLiteral_InvalidFloat_TooLargePositive)109 TEST_F(ParserImplTest, ConstLiteral_InvalidFloat_TooLargePositive) {
110 auto p = parser("1.2e+256");
111 auto c = p->const_literal();
112 EXPECT_FALSE(c.matched);
113 EXPECT_TRUE(c.errored);
114 EXPECT_EQ(p->error(), "1:1: f32 (1.2e+256) too large (positive)");
115 ASSERT_EQ(c.value, nullptr);
116 }
117
118 struct FloatLiteralTestCase {
119 const char* input;
120 float expected;
121 };
122
operator <<(std::ostream & out,FloatLiteralTestCase data)123 inline std::ostream& operator<<(std::ostream& out, FloatLiteralTestCase data) {
124 out << data.input;
125 return out;
126 }
127
128 class ParserImplFloatLiteralTest
129 : public ParserImplTestWithParam<FloatLiteralTestCase> {};
TEST_P(ParserImplFloatLiteralTest,Parse)130 TEST_P(ParserImplFloatLiteralTest, Parse) {
131 auto params = GetParam();
132 SCOPED_TRACE(params.input);
133 auto p = parser(params.input);
134 auto c = p->const_literal();
135 EXPECT_TRUE(c.matched);
136 EXPECT_FALSE(c.errored);
137 EXPECT_FALSE(p->has_error()) << p->error();
138 ASSERT_NE(c.value, nullptr);
139 ASSERT_TRUE(c->Is<ast::FloatLiteralExpression>());
140 EXPECT_FLOAT_EQ(c->As<ast::FloatLiteralExpression>()->value, params.expected);
141 }
142
143 FloatLiteralTestCase float_literal_test_cases[] = {
144 {"0.0", 0.0f}, // Zero
145 {"1.0", 1.0f}, // One
146 {"-1.0", -1.0f}, // MinusOne
147 {"1000000000.0", 1e9f}, // Billion
148 {"-0.0", std::copysign(0.0f, -5.0f)}, // NegativeZero
149 {"0.0", MakeFloat(0, 0, 0)}, // Zero
150 {"-0.0", MakeFloat(1, 0, 0)}, // NegativeZero
151 {"1.0", MakeFloat(0, 127, 0)}, // One
152 {"-1.0", MakeFloat(1, 127, 0)}, // NegativeOne
153 };
154 INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_Float,
155 ParserImplFloatLiteralTest,
156 testing::ValuesIn(float_literal_test_cases));
157
158 const float NegInf = MakeFloat(1, 255, 0);
159 const float PosInf = MakeFloat(0, 255, 0);
160 FloatLiteralTestCase hexfloat_literal_test_cases[] = {
161 // Regular numbers
162 {"0x0p+0", 0.f},
163 {"0x1p+0", 1.f},
164 {"0x1p+1", 2.f},
165 {"0x1.8p+1", 3.f},
166 {"0x1.99999ap-4", 0.1f},
167 {"0x1p-1", 0.5f},
168 {"0x1p-2", 0.25f},
169 {"0x1.8p-1", 0.75f},
170 {"-0x0p+0", -0.f},
171 {"-0x1p+0", -1.f},
172 {"-0x1p-1", -0.5f},
173 {"-0x1p-2", -0.25f},
174 {"-0x1.8p-1", -0.75f},
175
176 // Large numbers
177 {"0x1p+9", 512.f},
178 {"0x1p+10", 1024.f},
179 {"0x1.02p+10", 1024.f + 8.f},
180 {"-0x1p+9", -512.f},
181 {"-0x1p+10", -1024.f},
182 {"-0x1.02p+10", -1024.f - 8.f},
183
184 // Small numbers
185 {"0x1p-9", 1.0f / 512.f},
186 {"0x1p-10", 1.0f / 1024.f},
187 {"0x1.02p-3", 1.0f / 1024.f + 1.0f / 8.f},
188 {"-0x1p-9", 1.0f / -512.f},
189 {"-0x1p-10", 1.0f / -1024.f},
190 {"-0x1.02p-3", 1.0f / -1024.f - 1.0f / 8.f},
191
192 // Near lowest non-denorm
193 {"0x1p-124", std::ldexp(1.f * 8.f, -127)},
194 {"0x1p-125", std::ldexp(1.f * 4.f, -127)},
195 {"-0x1p-124", -std::ldexp(1.f * 8.f, -127)},
196 {"-0x1p-125", -std::ldexp(1.f * 4.f, -127)},
197
198 // Lowest non-denorm
199 {"0x1p-126", std::ldexp(1.f * 2.f, -127)},
200 {"-0x1p-126", -std::ldexp(1.f * 2.f, -127)},
201
202 // Denormalized values
203 {"0x1p-127", std::ldexp(1.f, -127)},
204 {"0x1p-128", std::ldexp(1.f / 2.f, -127)},
205 {"0x1p-129", std::ldexp(1.f / 4.f, -127)},
206 {"0x1p-130", std::ldexp(1.f / 8.f, -127)},
207 {"-0x1p-127", -std::ldexp(1.f, -127)},
208 {"-0x1p-128", -std::ldexp(1.f / 2.f, -127)},
209 {"-0x1p-129", -std::ldexp(1.f / 4.f, -127)},
210 {"-0x1p-130", -std::ldexp(1.f / 8.f, -127)},
211
212 {"0x1.8p-127", std::ldexp(1.f, -127) + (std::ldexp(1.f, -127) / 2.f)},
213 {"0x1.8p-128", std::ldexp(1.f, -127) / 2.f + (std::ldexp(1.f, -127) / 4.f)},
214
215 {"0x1p-149", MakeFloat(0, 0, 1)}, // +SmallestDenormal
216 {"0x1p-148", MakeFloat(0, 0, 2)}, // +BiggerDenormal
217 {"0x1.fffffcp-127", MakeFloat(0, 0, 0x7fffff)}, // +LargestDenormal
218 {"-0x1p-149", MakeFloat(1, 0, 1)}, // -SmallestDenormal
219 {"-0x1p-148", MakeFloat(1, 0, 2)}, // -BiggerDenormal
220 {"-0x1.fffffcp-127", MakeFloat(1, 0, 0x7fffff)}, // -LargestDenormal
221
222 {"0x1.2bfaf8p-127", MakeFloat(0, 0, 0xcafebe)}, // +Subnormal
223 {"-0x1.2bfaf8p-127", MakeFloat(1, 0, 0xcafebe)}, // -Subnormal
224 {"0x1.55554p-130", MakeFloat(0, 0, 0xaaaaa)}, // +Subnormal
225 {"-0x1.55554p-130", MakeFloat(1, 0, 0xaaaaa)}, // -Subnormal
226
227 // Nan -> Infinity
228 {"0x1.8p+128", PosInf},
229 {"0x1.0002p+128", PosInf},
230 {"0x1.0018p+128", PosInf},
231 {"0x1.01ep+128", PosInf},
232 {"0x1.fffffep+128", PosInf},
233 {"-0x1.8p+128", NegInf},
234 {"-0x1.0002p+128", NegInf},
235 {"-0x1.0018p+128", NegInf},
236 {"-0x1.01ep+128", NegInf},
237 {"-0x1.fffffep+128", NegInf},
238
239 // Infinity
240 {"0x1p+128", PosInf},
241 {"-0x1p+128", NegInf},
242 {"0x32p+127", PosInf},
243 {"0x32p+500", PosInf},
244 {"-0x32p+127", NegInf},
245 {"-0x32p+500", NegInf},
246
247 // Overflow -> Infinity
248 {"0x1p+129", PosInf},
249 {"0x1.1p+128", PosInf},
250 {"-0x1p+129", NegInf},
251 {"-0x1.1p+128", NegInf},
252 {"0x1.0p2147483520", PosInf}, // INT_MAX - 127 (largest valid exponent)
253
254 // Underflow -> Zero
255 {"0x1p-500", 0.f}, // Exponent underflows
256 {"-0x1p-500", -0.f},
257 {"0x0.00000000001p-126", 0.f}, // Fraction causes underflow
258 {"-0x0.0000000001p-127", -0.f},
259 {"0x0.01p-142", 0.f},
260 {"-0x0.01p-142", -0.f}, // Fraction causes additional underflow
261 {"0x1.0p-2147483520", 0}, // -(INT_MAX - 127) (smallest valid exponent)
262
263 // Zero with non-zero exponent -> Zero
264 {"0x0p+0", 0.f},
265 {"0x0p+1", 0.f},
266 {"0x0p-1", 0.f},
267 {"0x0p+9999999999", 0.f},
268 {"0x0p-9999999999", 0.f},
269 // Same, but with very large positive exponents that would cause overflow
270 // if the mantissa were non-zero.
271 {"0x0p+4000000000", 0.f}, // 4 billion:
272 {"0x0p+40000000000", 0.f}, // 40 billion
273 {"-0x0p+40000000000", 0.f}, // As above 2, but negative mantissa
274 {"-0x0p+400000000000", 0.f},
275 {"0x0.00p+4000000000", 0.f}, // As above 4, but with fractional part
276 {"0x0.00p+40000000000", 0.f},
277 {"-0x0.00p+40000000000", 0.f},
278 {"-0x0.00p+400000000000", 0.f},
279 {"0x0p-4000000000", 0.f}, // As above 8, but with negative exponents
280 {"0x0p-40000000000", 0.f},
281 {"-0x0p-40000000000", 0.f},
282 {"-0x0p-400000000000", 0.f},
283 {"0x0.00p-4000000000", 0.f},
284 {"0x0.00p-40000000000", 0.f},
285 {"-0x0.00p-40000000000", 0.f},
286 {"-0x0.00p-400000000000", 0.f},
287
288 // Test parsing
289 {"0x0p0", 0.f},
290 {"0x0p-0", 0.f},
291 {"0x0p+000", 0.f},
292 {"0x00000000000000p+000000000000000", 0.f},
293 {"0x00000000000000p-000000000000000", 0.f},
294 {"0x00000000000001p+000000000000000", 1.f},
295 {"0x00000000000001p-000000000000000", 1.f},
296 {"0x0000000000000000000001.99999ap-000000000000000004", 0.1f},
297 {"0x2p+0", 2.f},
298 {"0xFFp+0", 255.f},
299 {"0x0.8p+0", 0.5f},
300 {"0x0.4p+0", 0.25f},
301 {"0x0.4p+1", 2 * 0.25f},
302 {"0x0.4p+2", 4 * 0.25f},
303 {"0x123Ep+1", 9340.f},
304 {"-0x123Ep+1", -9340.f},
305 {"0x1a2b3cP12", 7.024656e+09f},
306 {"-0x1a2b3cP12", -7.024656e+09f},
307
308 // Examples without a binary exponent part.
309 {"0x1.", 1.0f},
310 {"0x.8", 0.5f},
311 {"0x1.8", 1.5f},
312 {"-0x1.", -1.0f},
313 {"-0x.8", -0.5f},
314 {"-0x1.8", -1.5f},
315
316 // Examples with a binary exponent and a 'f' suffix.
317 {"0x1.p0f", 1.0f},
318 {"0x.8p2f", 2.0f},
319 {"0x1.8p-1f", 0.75f},
320 {"0x2p-2f", 0.5f}, // No binary point
321 {"-0x1.p0f", -1.0f},
322 {"-0x.8p2f", -2.0f},
323 {"-0x1.8p-1f", -0.75f},
324 {"-0x2p-2f", -0.5f}, // No binary point
325 };
326 INSTANTIATE_TEST_SUITE_P(ParserImplFloatLiteralTest_HexFloat,
327 ParserImplFloatLiteralTest,
328 testing::ValuesIn(hexfloat_literal_test_cases));
329
330 struct InvalidLiteralTestCase {
331 const char* input;
332 const char* error_msg;
333 };
334 class ParserImplInvalidLiteralTest
335 : public ParserImplTestWithParam<InvalidLiteralTestCase> {};
TEST_P(ParserImplInvalidLiteralTest,Parse)336 TEST_P(ParserImplInvalidLiteralTest, Parse) {
337 auto params = GetParam();
338 SCOPED_TRACE(params.input);
339 auto p = parser(params.input);
340 auto c = p->const_literal();
341 EXPECT_FALSE(c.matched);
342 EXPECT_TRUE(c.errored);
343 EXPECT_EQ(p->error(), params.error_msg);
344 ASSERT_EQ(c.value, nullptr);
345 }
346
347 InvalidLiteralTestCase invalid_hexfloat_mantissa_too_large_cases[] = {
348 {"0x1.ffffffff8p0", "1:1: mantissa is too large for hex float"},
349 {"0x1f.fffffff8p0", "1:1: mantissa is too large for hex float"},
350 {"0x1ff.ffffff8p0", "1:1: mantissa is too large for hex float"},
351 {"0x1fff.fffff8p0", "1:1: mantissa is too large for hex float"},
352 {"0x1ffff.ffff8p0", "1:1: mantissa is too large for hex float"},
353 {"0x1fffff.fff8p0", "1:1: mantissa is too large for hex float"},
354 {"0x1ffffff.ff8p0", "1:1: mantissa is too large for hex float"},
355 {"0x1fffffff.f8p0", "1:1: mantissa is too large for hex float"},
356 {"0x1ffffffff.8p0", "1:1: mantissa is too large for hex float"},
357 {"0x1ffffffff8.p0", "1:1: mantissa is too large for hex float"},
358 };
359 INSTANTIATE_TEST_SUITE_P(
360 ParserImplInvalidLiteralTest_HexFloatMantissaTooLarge,
361 ParserImplInvalidLiteralTest,
362 testing::ValuesIn(invalid_hexfloat_mantissa_too_large_cases));
363
364 InvalidLiteralTestCase invalid_hexfloat_exponent_too_large_cases[] = {
365 {"0x1p+2147483521", "1:1: exponent is too large for hex float"},
366 {"0x1p-2147483521", "1:1: exponent is too large for hex float"},
367 {"0x1p+4294967296", "1:1: exponent is too large for hex float"},
368 {"0x1p-4294967296", "1:1: exponent is too large for hex float"},
369 };
370 INSTANTIATE_TEST_SUITE_P(
371 ParserImplInvalidLiteralTest_HexFloatExponentTooLarge,
372 ParserImplInvalidLiteralTest,
373 testing::ValuesIn(invalid_hexfloat_exponent_too_large_cases));
374
375 InvalidLiteralTestCase invalid_hexfloat_exponent_missing_cases[] = {
376 // Lower case p
377 {"0x0p", "1:1: expected an exponent value for hex float"},
378 {"0x0p+", "1:1: expected an exponent value for hex float"},
379 {"0x0p-", "1:1: expected an exponent value for hex float"},
380 {"0x1.0p", "1:1: expected an exponent value for hex float"},
381 {"0x0.1p", "1:1: expected an exponent value for hex float"},
382 // Upper case p
383 {"0x0P", "1:1: expected an exponent value for hex float"},
384 {"0x0P+", "1:1: expected an exponent value for hex float"},
385 {"0x0P-", "1:1: expected an exponent value for hex float"},
386 {"0x1.0P", "1:1: expected an exponent value for hex float"},
387 {"0x0.1P", "1:1: expected an exponent value for hex float"},
388 };
389 INSTANTIATE_TEST_SUITE_P(
390 ParserImplInvalidLiteralTest_HexFloatExponentMissing,
391 ParserImplInvalidLiteralTest,
392 testing::ValuesIn(invalid_hexfloat_exponent_missing_cases));
393
TEST_F(ParserImplTest,ConstLiteral_FloatHighest)394 TEST_F(ParserImplTest, ConstLiteral_FloatHighest) {
395 const auto highest = std::numeric_limits<float>::max();
396 const auto expected_highest = 340282346638528859811704183484516925440.0f;
397 if (highest < expected_highest || highest > expected_highest) {
398 GTEST_SKIP() << "std::numeric_limits<float>::max() is not as expected for "
399 "this target";
400 }
401 auto p = parser("340282346638528859811704183484516925440.0");
402 auto c = p->const_literal();
403 EXPECT_TRUE(c.matched);
404 EXPECT_FALSE(c.errored);
405 EXPECT_FALSE(p->has_error()) << p->error();
406 ASSERT_NE(c.value, nullptr);
407 ASSERT_TRUE(c->Is<ast::FloatLiteralExpression>());
408 EXPECT_FLOAT_EQ(c->As<ast::FloatLiteralExpression>()->value,
409 std::numeric_limits<float>::max());
410 EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 42u}}));
411 }
412
TEST_F(ParserImplTest,ConstLiteral_FloatLowest)413 TEST_F(ParserImplTest, ConstLiteral_FloatLowest) {
414 // Some compilers complain if you test floating point numbers for equality.
415 // So say it via two inequalities.
416 const auto lowest = std::numeric_limits<float>::lowest();
417 const auto expected_lowest = -340282346638528859811704183484516925440.0f;
418 if (lowest < expected_lowest || lowest > expected_lowest) {
419 GTEST_SKIP()
420 << "std::numeric_limits<float>::lowest() is not as expected for "
421 "this target";
422 }
423
424 auto p = parser("-340282346638528859811704183484516925440.0");
425 auto c = p->const_literal();
426 EXPECT_TRUE(c.matched);
427 EXPECT_FALSE(c.errored);
428 EXPECT_FALSE(p->has_error()) << p->error();
429 ASSERT_NE(c.value, nullptr);
430 ASSERT_TRUE(c->Is<ast::FloatLiteralExpression>());
431 EXPECT_FLOAT_EQ(c->As<ast::FloatLiteralExpression>()->value,
432 std::numeric_limits<float>::lowest());
433 EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 43u}}));
434 }
435
TEST_F(ParserImplTest,ConstLiteral_True)436 TEST_F(ParserImplTest, ConstLiteral_True) {
437 auto p = parser("true");
438 auto c = p->const_literal();
439 EXPECT_TRUE(c.matched);
440 EXPECT_FALSE(c.errored);
441 EXPECT_FALSE(p->has_error()) << p->error();
442 ASSERT_NE(c.value, nullptr);
443 ASSERT_TRUE(c->Is<ast::BoolLiteralExpression>());
444 EXPECT_TRUE(c->As<ast::BoolLiteralExpression>()->value);
445 EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
446 }
447
TEST_F(ParserImplTest,ConstLiteral_False)448 TEST_F(ParserImplTest, ConstLiteral_False) {
449 auto p = parser("false");
450 auto c = p->const_literal();
451 EXPECT_TRUE(c.matched);
452 EXPECT_FALSE(c.errored);
453 EXPECT_FALSE(p->has_error()) << p->error();
454 ASSERT_NE(c.value, nullptr);
455 ASSERT_TRUE(c->Is<ast::BoolLiteralExpression>());
456 EXPECT_FALSE(c->As<ast::BoolLiteralExpression>()->value);
457 EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 6u}}));
458 }
459
TEST_F(ParserImplTest,ConstLiteral_NoMatch)460 TEST_F(ParserImplTest, ConstLiteral_NoMatch) {
461 auto p = parser("another-token");
462 auto c = p->const_literal();
463 EXPECT_FALSE(c.matched);
464 EXPECT_FALSE(c.errored);
465 EXPECT_FALSE(p->has_error()) << p->error();
466 ASSERT_EQ(c.value, nullptr);
467 }
468
469 } // namespace
470 } // namespace wgsl
471 } // namespace reader
472 } // namespace tint
473