blob: dcd2b440de00fa46167940f174a85887fc0998a3 [file] [log] [blame]
Dan Sinclair6e581892020-03-02 15:47:43 -05001// 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.h"
16
17#include <memory>
dan sinclair3ffec802020-04-06 19:37:37 +000018#include <vector>
Dan Sinclair6e581892020-03-02 15:47:43 -050019
20#include "src/ast/array_accessor_expression.h"
21#include "src/ast/as_expression.h"
dan sinclair1c9b4862020-04-07 19:27:41 +000022#include "src/ast/binary_expression.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050023#include "src/ast/binding_decoration.h"
24#include "src/ast/bool_literal.h"
25#include "src/ast/break_statement.h"
26#include "src/ast/builtin_decoration.h"
27#include "src/ast/call_expression.h"
28#include "src/ast/case_statement.h"
29#include "src/ast/cast_expression.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050030#include "src/ast/continue_statement.h"
31#include "src/ast/decorated_variable.h"
dan sinclairf75f2cd2020-07-25 14:33:13 +000032#include "src/ast/discard_statement.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050033#include "src/ast/else_statement.h"
34#include "src/ast/fallthrough_statement.h"
35#include "src/ast/float_literal.h"
36#include "src/ast/identifier_expression.h"
37#include "src/ast/if_statement.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050038#include "src/ast/location_decoration.h"
39#include "src/ast/member_accessor_expression.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050040#include "src/ast/return_statement.h"
dan sinclaira322f5d2020-03-30 22:46:06 +000041#include "src/ast/scalar_constructor_expression.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050042#include "src/ast/set_decoration.h"
dan sinclairc6f29472020-06-02 20:11:44 +000043#include "src/ast/sint_literal.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050044#include "src/ast/struct_member_offset_decoration.h"
45#include "src/ast/switch_statement.h"
46#include "src/ast/type/alias_type.h"
47#include "src/ast/type/array_type.h"
48#include "src/ast/type/bool_type.h"
49#include "src/ast/type/f32_type.h"
50#include "src/ast/type/i32_type.h"
51#include "src/ast/type/matrix_type.h"
52#include "src/ast/type/pointer_type.h"
53#include "src/ast/type/struct_type.h"
54#include "src/ast/type/u32_type.h"
55#include "src/ast/type/vector_type.h"
56#include "src/ast/type/void_type.h"
dan sinclaira322f5d2020-03-30 22:46:06 +000057#include "src/ast/type_constructor_expression.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050058#include "src/ast/uint_literal.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050059#include "src/ast/unary_op.h"
60#include "src/ast/unary_op_expression.h"
dan sinclaire49bd5e2020-03-30 22:46:48 +000061#include "src/ast/variable_decl_statement.h"
Dan Sinclair6e581892020-03-02 15:47:43 -050062#include "src/reader/wgsl/lexer.h"
63#include "src/type_manager.h"
64
65namespace tint {
66namespace reader {
67namespace wgsl {
dan sinclair1d2ad812020-06-01 13:43:11 +000068namespace {
69
70ast::Builtin ident_to_builtin(const std::string& str) {
71 if (str == "position") {
72 return ast::Builtin::kPosition;
73 }
74 if (str == "vertex_idx") {
75 return ast::Builtin::kVertexIdx;
76 }
77 if (str == "instance_idx") {
78 return ast::Builtin::kInstanceIdx;
79 }
80 if (str == "front_facing") {
81 return ast::Builtin::kFrontFacing;
82 }
83 if (str == "frag_coord") {
84 return ast::Builtin::kFragCoord;
85 }
86 if (str == "frag_depth") {
87 return ast::Builtin::kFragDepth;
88 }
dan sinclair1d2ad812020-06-01 13:43:11 +000089 if (str == "workgroup_size") {
90 return ast::Builtin::kWorkgroupSize;
91 }
92 if (str == "local_invocation_id") {
93 return ast::Builtin::kLocalInvocationId;
94 }
95 if (str == "local_invocation_idx") {
96 return ast::Builtin::kLocalInvocationIdx;
97 }
98 if (str == "global_invocation_id") {
99 return ast::Builtin::kGlobalInvocationId;
100 }
101 return ast::Builtin::kNone;
102}
103
104} // namespace
Dan Sinclair6e581892020-03-02 15:47:43 -0500105
David Netoa8cd18e2020-03-27 00:47:16 +0000106ParserImpl::ParserImpl(Context* ctx, const std::string& input)
107 : ctx_(*ctx), lexer_(std::make_unique<Lexer>(input)) {}
Dan Sinclair6e581892020-03-02 15:47:43 -0500108
109ParserImpl::~ParserImpl() = default;
110
111void ParserImpl::set_error(const Token& t, const std::string& err) {
112 auto prefix =
113 std::to_string(t.line()) + ":" + std::to_string(t.column()) + ": ";
114
115 if (t.IsReservedKeyword()) {
116 error_ = prefix + "reserved token (" + t.to_str() + ") found";
117 return;
118 }
119 if (t.IsError()) {
120 error_ = prefix + t.to_str();
121 return;
122 }
123
124 if (err.size() != 0) {
125 error_ = prefix + err;
126 } else {
127 error_ = prefix + "invalid token (" + t.to_name() + ") encountered";
128 }
129}
130
131void ParserImpl::set_error(const Token& t) {
132 set_error(t, "");
133}
134
135Token ParserImpl::next() {
136 if (!token_queue_.empty()) {
137 auto t = token_queue_.front();
138 token_queue_.pop_front();
139 return t;
140 }
141 return lexer_->next();
142}
143
144Token ParserImpl::peek(size_t idx) {
145 while (token_queue_.size() < (idx + 1))
146 token_queue_.push_back(lexer_->next());
147
148 return token_queue_[idx];
149}
150
151Token ParserImpl::peek() {
152 return peek(0);
153}
154
155void ParserImpl::register_alias(const std::string& name,
156 ast::type::Type* type) {
157 assert(type);
158 registered_aliases_[name] = type;
159}
160
161ast::type::Type* ParserImpl::get_alias(const std::string& name) {
162 if (registered_aliases_.find(name) == registered_aliases_.end()) {
163 return nullptr;
164 }
165 return registered_aliases_[name];
166}
167
168bool ParserImpl::Parse() {
169 translation_unit();
170 return !has_error();
171}
172
173// translation_unit
174// : global_decl* EOF
175void ParserImpl::translation_unit() {
176 for (;;) {
177 global_decl();
178 if (has_error())
179 return;
180
181 if (peek().IsEof())
182 break;
183 }
184
185 assert(module_.IsValid());
186}
187
188// global_decl
189// : SEMICOLON
190// | import_decl SEMICOLON
191// | global_variable_decl SEMICLON
192// | global_constant_decl SEMICOLON
193// | entry_point_decl SEMICOLON
194// | type_alias SEMICOLON
195// | function_decl
196void ParserImpl::global_decl() {
197 auto t = peek();
198 if (t.IsEof())
199 return;
200
201 if (t.IsSemicolon()) {
202 next(); // consume the peek
203 return;
204 }
205
206 auto import = import_decl();
207 if (has_error())
208 return;
209 if (import != nullptr) {
210 t = next();
211 if (!t.IsSemicolon()) {
212 set_error(t, "missing ';' for import");
213 return;
214 }
215 module_.AddImport(std::move(import));
216 return;
217 }
218
219 auto gv = global_variable_decl();
220 if (has_error())
221 return;
222 if (gv != nullptr) {
223 t = next();
224 if (!t.IsSemicolon()) {
225 set_error(t, "missing ';' for variable declaration");
226 return;
227 }
228 module_.AddGlobalVariable(std::move(gv));
229 return;
230 }
231
232 auto gc = global_constant_decl();
233 if (has_error())
234 return;
235 if (gc != nullptr) {
236 t = next();
237 if (!t.IsSemicolon()) {
238 set_error(t, "missing ';' for constant declaration");
239 return;
240 }
241 module_.AddGlobalVariable(std::move(gc));
242 return;
243 }
244
245 auto ep = entry_point_decl();
246 if (has_error())
247 return;
248 if (ep != nullptr) {
249 t = next();
250 if (!t.IsSemicolon()) {
251 set_error(t, "missing ';' for entry point");
252 return;
253 }
254 module_.AddEntryPoint(std::move(ep));
255 return;
256 }
257
Ryan Harrison0caab672020-04-15 20:47:55 +0000258 auto* ta = type_alias();
Dan Sinclair6e581892020-03-02 15:47:43 -0500259 if (has_error())
260 return;
261 if (ta != nullptr) {
262 t = next();
263 if (!t.IsSemicolon()) {
264 set_error(t, "missing ';' for type alias");
265 return;
266 }
267 module_.AddAliasType(ta);
268 return;
269 }
270
271 auto func = function_decl();
272 if (has_error())
273 return;
274 if (func != nullptr) {
275 module_.AddFunction(std::move(func));
276 return;
277 }
278
279 set_error(t);
280}
281
282// import_decl
283// : IMPORT STRING_LITERAL AS (IDENT NAMESPACE)* IDENT
284std::unique_ptr<ast::Import> ParserImpl::import_decl() {
285 auto t = peek();
286 if (!t.IsImport())
287 return {};
288
289 auto source = t.source();
290 next(); // consume the import token
291
292 t = next();
293 if (!t.IsStringLiteral()) {
294 set_error(t, "missing path for import");
295 return {};
296 }
297 auto path = t.to_str();
298 if (path.length() == 0) {
299 set_error(t, "import path must not be empty");
300 return {};
301 }
302
303 t = next();
304 if (!t.IsAs()) {
305 set_error(t, "missing 'as' for import");
306 return {};
307 }
308
309 std::string name = "";
310 for (;;) {
311 t = peek();
312 if (!t.IsIdentifier()) {
313 break;
314 }
315 next(); // consume the peek
316
317 name += t.to_str();
318
319 t = peek();
320 if (!t.IsNamespace()) {
321 break;
322 }
323 next(); // consume the peek
324
325 name += "::";
326 }
327 if (name.length() == 0) {
328 if (t.IsEof() || t.IsSemicolon()) {
329 set_error(t, "missing name for import");
330 } else {
331 set_error(t, "invalid name for import");
332 }
333 return {};
334 }
335 if (name.length() > 2) {
336 auto end = name.length() - 1;
337 if (name[end] == ':' && name[end - 1] == ':') {
338 set_error(t, "invalid name for import");
339 return {};
340 }
341 }
342 return std::make_unique<ast::Import>(source, path, name);
343}
344
345// global_variable_decl
346// : variable_decoration_list variable_decl
347// | variable_decoration_list variable_decl EQUAL const_expr
348std::unique_ptr<ast::Variable> ParserImpl::global_variable_decl() {
349 auto decos = variable_decoration_list();
350 if (has_error())
351 return nullptr;
352
353 auto var = variable_decl();
354 if (has_error())
355 return nullptr;
356 if (var == nullptr) {
357 if (decos.size() > 0)
358 set_error(peek(), "error parsing variable declaration");
359
360 return nullptr;
361 }
362
363 if (decos.size() > 0) {
Dan Sinclair3a1368d2020-03-10 17:47:56 +0000364 auto dv = std::make_unique<ast::DecoratedVariable>(std::move(var));
Dan Sinclair6e581892020-03-02 15:47:43 -0500365 dv->set_decorations(std::move(decos));
366
367 var = std::move(dv);
368 }
369
370 auto t = peek();
371 if (t.IsEqual()) {
372 next(); // Consume the peek
373
374 auto expr = const_expr();
375 if (has_error())
376 return nullptr;
377 if (expr == nullptr) {
378 set_error(peek(), "invalid expression");
379 return nullptr;
380 }
381
dan sinclaira322f5d2020-03-30 22:46:06 +0000382 var->set_constructor(std::move(expr));
Dan Sinclair6e581892020-03-02 15:47:43 -0500383 }
384 return var;
385}
386
387// global_constant_decl
388// : CONST variable_ident_decl EQUAL const_expr
389std::unique_ptr<ast::Variable> ParserImpl::global_constant_decl() {
390 auto t = peek();
391 if (!t.IsConst())
392 return nullptr;
393
394 auto source = t.source();
395 next(); // Consume the peek
396
397 std::string name;
398 ast::type::Type* type;
399 std::tie(name, type) = variable_ident_decl();
400 if (has_error())
401 return nullptr;
dan sinclairf26d9a82020-03-26 15:31:36 +0000402 if (name.empty() || type == nullptr) {
Dan Sinclair6e581892020-03-02 15:47:43 -0500403 set_error(peek(), "error parsing constant variable identifier");
404 return nullptr;
405 }
406
407 auto var = std::make_unique<ast::Variable>(source, name,
408 ast::StorageClass::kNone, type);
409 var->set_is_const(true);
410
411 t = next();
412 if (!t.IsEqual()) {
413 set_error(t, "missing = for const declaration");
414 return nullptr;
415 }
416
417 auto init = const_expr();
418 if (has_error())
419 return nullptr;
420 if (init == nullptr) {
dan sinclaira322f5d2020-03-30 22:46:06 +0000421 set_error(peek(), "error parsing scalar constructor");
Dan Sinclair6e581892020-03-02 15:47:43 -0500422 return nullptr;
423 }
dan sinclaira322f5d2020-03-30 22:46:06 +0000424 var->set_constructor(std::move(init));
Dan Sinclair6e581892020-03-02 15:47:43 -0500425
426 return var;
427}
428
429// variable_decoration_list
dan sinclair1d2ad812020-06-01 13:43:11 +0000430// : ATTR_LEFT (variable_decoration COMMA)* variable_decoration ATTR_RIGHT
dan sinclair3ffec802020-04-06 19:37:37 +0000431ast::VariableDecorationList ParserImpl::variable_decoration_list() {
432 ast::VariableDecorationList decos;
Dan Sinclair6e581892020-03-02 15:47:43 -0500433
434 auto t = peek();
435 if (!t.IsAttrLeft())
436 return decos;
437
438 next(); // consume the peek
439
440 auto deco = variable_decoration();
441 if (has_error())
442 return {};
443 if (deco == nullptr) {
444 t = peek();
445 if (t.IsAttrRight()) {
446 set_error(t, "empty variable decoration list");
447 return {};
448 }
449 set_error(t, "missing variable decoration for decoration list");
450 return {};
451 }
452 for (;;) {
453 decos.push_back(std::move(deco));
454
455 t = peek();
456 if (!t.IsComma()) {
457 break;
458 }
459 next(); // consume the peek
460
461 deco = variable_decoration();
462 if (has_error())
463 return {};
464 if (deco == nullptr) {
465 set_error(peek(), "missing variable decoration after comma");
466 return {};
467 }
468 }
469
470 t = peek();
471 if (!t.IsAttrRight()) {
472 deco = variable_decoration();
473 if (deco != nullptr) {
474 set_error(t, "missing comma in variable decoration list");
475 return {};
476 }
477 set_error(t, "missing ]] for variable decoration");
478 return {};
479 }
480 next(); // consume the peek
481
482 return decos;
483}
484
485// variable_decoration
486// : LOCATION INT_LITERAL
dan sinclair1d2ad812020-06-01 13:43:11 +0000487// | BUILTIN IDENT
Dan Sinclair6e581892020-03-02 15:47:43 -0500488// | BINDING INT_LITERAL
489// | SET INT_LITERAL
490std::unique_ptr<ast::VariableDecoration> ParserImpl::variable_decoration() {
491 auto t = peek();
492 if (t.IsLocation()) {
493 next(); // consume the peek
494
495 t = next();
dan sinclairc6f29472020-06-02 20:11:44 +0000496 if (!t.IsSintLiteral()) {
Dan Sinclair6e581892020-03-02 15:47:43 -0500497 set_error(t, "invalid value for location decoration");
498 return {};
499 }
500
501 return std::make_unique<ast::LocationDecoration>(t.to_i32());
502 }
503 if (t.IsBuiltin()) {
504 next(); // consume the peek
505
dan sinclair1d2ad812020-06-01 13:43:11 +0000506 t = next();
507 if (!t.IsIdentifier() || t.to_str().empty()) {
508 set_error(t, "expected identifier for builtin");
Dan Sinclair6e581892020-03-02 15:47:43 -0500509 return {};
dan sinclair1d2ad812020-06-01 13:43:11 +0000510 }
511
512 ast::Builtin builtin = ident_to_builtin(t.to_str());
Dan Sinclair6e581892020-03-02 15:47:43 -0500513 if (builtin == ast::Builtin::kNone) {
dan sinclair1d2ad812020-06-01 13:43:11 +0000514 set_error(t, "invalid value for builtin decoration");
Dan Sinclair6e581892020-03-02 15:47:43 -0500515 return {};
516 }
517
518 return std::make_unique<ast::BuiltinDecoration>(builtin);
519 }
520 if (t.IsBinding()) {
521 next(); // consume the peek
522
523 t = next();
dan sinclairc6f29472020-06-02 20:11:44 +0000524 if (!t.IsSintLiteral()) {
Dan Sinclair6e581892020-03-02 15:47:43 -0500525 set_error(t, "invalid value for binding decoration");
526 return {};
527 }
528
529 return std::make_unique<ast::BindingDecoration>(t.to_i32());
530 }
531 if (t.IsSet()) {
532 next(); // consume the peek
533
534 t = next();
dan sinclairc6f29472020-06-02 20:11:44 +0000535 if (!t.IsSintLiteral()) {
Dan Sinclair6e581892020-03-02 15:47:43 -0500536 set_error(t, "invalid value for set decoration");
537 return {};
538 }
539
540 return std::make_unique<ast::SetDecoration>(t.to_i32());
541 }
542
543 return nullptr;
544}
545
Dan Sinclair6e581892020-03-02 15:47:43 -0500546// variable_decl
547// : VAR variable_storage_decoration? variable_ident_decl
548std::unique_ptr<ast::Variable> ParserImpl::variable_decl() {
549 auto t = peek();
550 auto source = t.source();
551 if (!t.IsVar())
552 return nullptr;
553
554 next(); // Consume the peek
555
556 auto sc = variable_storage_decoration();
557 if (has_error())
558 return {};
559
560 std::string name;
561 ast::type::Type* type;
562 std::tie(name, type) = variable_ident_decl();
563 if (has_error())
564 return nullptr;
dan sinclairf26d9a82020-03-26 15:31:36 +0000565 if (name.empty() || type == nullptr) {
Dan Sinclair6e581892020-03-02 15:47:43 -0500566 set_error(peek(), "invalid identifier declaration");
567 return nullptr;
568 }
569
570 return std::make_unique<ast::Variable>(source, name, sc, type);
571}
572
573// variable_ident_decl
574// : IDENT COLON type_decl
575std::pair<std::string, ast::type::Type*> ParserImpl::variable_ident_decl() {
576 auto t = peek();
577 if (!t.IsIdentifier())
578 return {};
579
580 auto name = t.to_str();
581 next(); // Consume the peek
582
583 t = next();
584 if (!t.IsColon()) {
585 set_error(t, "missing : for identifier declaration");
586 return {};
587 }
588
Ryan Harrison0caab672020-04-15 20:47:55 +0000589 auto* type = type_decl();
Dan Sinclair6e581892020-03-02 15:47:43 -0500590 if (has_error())
591 return {};
592 if (type == nullptr) {
593 set_error(peek(), "invalid type for identifier declaration");
594 return {};
595 }
596
597 return {name, type};
598}
599
600// variable_storage_decoration
601// : LESS_THAN storage_class GREATER_THAN
602ast::StorageClass ParserImpl::variable_storage_decoration() {
603 auto t = peek();
604 if (!t.IsLessThan())
605 return ast::StorageClass::kNone;
606
607 next(); // Consume the peek
608
609 auto sc = storage_class();
610 if (has_error())
611 return sc;
612 if (sc == ast::StorageClass::kNone) {
613 set_error(peek(), "invalid storage class for variable decoration");
614 return sc;
615 }
616
617 t = next();
618 if (!t.IsGreaterThan()) {
619 set_error(t, "missing > for variable decoration");
620 return ast::StorageClass::kNone;
621 }
622
623 return sc;
624}
625
626// type_alias
627// : TYPE IDENT EQUAL type_decl
628// | TYPE IDENT EQUAL struct_decl
629ast::type::AliasType* ParserImpl::type_alias() {
630 auto t = peek();
631 if (!t.IsType())
632 return nullptr;
633
634 next(); // Consume the peek
635
636 t = next();
637 if (!t.IsIdentifier()) {
638 set_error(t, "missing identifier for type alias");
639 return nullptr;
640 }
641 auto name = t.to_str();
642
643 t = next();
644 if (!t.IsEqual()) {
645 set_error(t, "missing = for type alias");
646 return nullptr;
647 }
648
Ryan Harrison0caab672020-04-15 20:47:55 +0000649 auto* type = type_decl();
Dan Sinclair6e581892020-03-02 15:47:43 -0500650 if (has_error())
651 return nullptr;
652 if (type == nullptr) {
653 auto str = struct_decl();
654 if (has_error())
655 return nullptr;
656 if (str == nullptr) {
657 set_error(peek(), "invalid type alias");
658 return nullptr;
659 }
660
661 str->set_name(name);
David Netoa8cd18e2020-03-27 00:47:16 +0000662 type = ctx_.type_mgr().Get(std::move(str));
Dan Sinclair6e581892020-03-02 15:47:43 -0500663 }
664 if (type == nullptr) {
665 set_error(peek(), "invalid type for alias");
666 return nullptr;
667 }
668
Ryan Harrison0caab672020-04-15 20:47:55 +0000669 auto* alias =
David Netoa8cd18e2020-03-27 00:47:16 +0000670 ctx_.type_mgr().Get(std::make_unique<ast::type::AliasType>(name, type));
Dan Sinclair6e581892020-03-02 15:47:43 -0500671 register_alias(name, alias);
672
673 return alias->AsAlias();
674}
675
676// type_decl
677// : IDENTIFIER
678// | BOOL
679// | FLOAT32
680// | INT32
681// | UINT32
682// | VEC2 LESS_THAN type_decl GREATER_THAN
683// | VEC3 LESS_THAN type_decl GREATER_THAN
dan sinclair091b2b52020-06-01 13:44:06 +0000684// | VEC4 LESS_THAN type_decl GREATER_THAN
Dan Sinclair6e581892020-03-02 15:47:43 -0500685// | PTR LESS_THAN storage_class, type_decl GREATER_THAN
dan sinclairc8a85aa2020-07-30 16:50:25 +0000686// | array_decoration_list? ARRAY LESS_THAN type_decl COMMA
687// INT_LITERAL GREATER_THAN
688// | array_decoration_list? ARRAY LESS_THAN type_decl
689// GREATER_THAN
Dan Sinclair6e581892020-03-02 15:47:43 -0500690// | MAT2x2 LESS_THAN type_decl GREATER_THAN
691// | MAT2x3 LESS_THAN type_decl GREATER_THAN
692// | MAT2x4 LESS_THAN type_decl GREATER_THAN
693// | MAT3x2 LESS_THAN type_decl GREATER_THAN
694// | MAT3x3 LESS_THAN type_decl GREATER_THAN
695// | MAT3x4 LESS_THAN type_decl GREATER_THAN
696// | MAT4x2 LESS_THAN type_decl GREATER_THAN
697// | MAT4x3 LESS_THAN type_decl GREATER_THAN
698// | MAT4x4 LESS_THAN type_decl GREATER_THAN
699ast::type::Type* ParserImpl::type_decl() {
Dan Sinclair6e581892020-03-02 15:47:43 -0500700 auto t = peek();
701 if (t.IsIdentifier()) {
702 next(); // Consume the peek
Ryan Harrison0caab672020-04-15 20:47:55 +0000703 auto* alias = get_alias(t.to_str());
Dan Sinclair6e581892020-03-02 15:47:43 -0500704 if (alias == nullptr) {
705 set_error(t, "unknown type alias '" + t.to_str() + "'");
706 return nullptr;
707 }
708 return alias;
709 }
710 if (t.IsBool()) {
711 next(); // Consume the peek
David Netoa8cd18e2020-03-27 00:47:16 +0000712 return ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>());
Dan Sinclair6e581892020-03-02 15:47:43 -0500713 }
714 if (t.IsF32()) {
715 next(); // Consume the peek
David Netoa8cd18e2020-03-27 00:47:16 +0000716 return ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>());
Dan Sinclair6e581892020-03-02 15:47:43 -0500717 }
718 if (t.IsI32()) {
719 next(); // Consume the peek
David Netoa8cd18e2020-03-27 00:47:16 +0000720 return ctx_.type_mgr().Get(std::make_unique<ast::type::I32Type>());
Dan Sinclair6e581892020-03-02 15:47:43 -0500721 }
722 if (t.IsU32()) {
723 next(); // Consume the peek
David Netoa8cd18e2020-03-27 00:47:16 +0000724 return ctx_.type_mgr().Get(std::make_unique<ast::type::U32Type>());
Dan Sinclair6e581892020-03-02 15:47:43 -0500725 }
726 if (t.IsVec2() || t.IsVec3() || t.IsVec4()) {
727 return type_decl_vector(t);
728 }
729 if (t.IsPtr()) {
730 return type_decl_pointer(t);
731 }
dan sinclairc8a85aa2020-07-30 16:50:25 +0000732
733 auto deco = array_decoration_list();
734 if (has_error()) {
735 return nullptr;
736 }
737 if (deco != 0) {
738 t = peek();
739 }
740 if (deco != 0 && !t.IsArray()) {
741 set_error(t, "found array decoration but no array");
742 return nullptr;
743 }
Dan Sinclair6e581892020-03-02 15:47:43 -0500744 if (t.IsArray()) {
dan sinclairc8a85aa2020-07-30 16:50:25 +0000745 return type_decl_array(t, deco);
Dan Sinclair6e581892020-03-02 15:47:43 -0500746 }
747 if (t.IsMat2x2() || t.IsMat2x3() || t.IsMat2x4() || t.IsMat3x2() ||
748 t.IsMat3x3() || t.IsMat3x4() || t.IsMat4x2() || t.IsMat4x3() ||
749 t.IsMat4x4()) {
750 return type_decl_matrix(t);
751 }
752 return nullptr;
753}
754
755ast::type::Type* ParserImpl::type_decl_pointer(Token t) {
756 next(); // Consume the peek
757
758 t = next();
759 if (!t.IsLessThan()) {
760 set_error(t, "missing < for ptr declaration");
761 return nullptr;
762 }
763
764 auto sc = storage_class();
765 if (has_error())
766 return nullptr;
767 if (sc == ast::StorageClass::kNone) {
768 set_error(peek(), "missing storage class for ptr declaration");
769 return nullptr;
770 }
771
772 t = next();
773 if (!t.IsComma()) {
774 set_error(t, "missing , for ptr declaration");
775 return nullptr;
776 }
777
Ryan Harrison0caab672020-04-15 20:47:55 +0000778 auto* subtype = type_decl();
Dan Sinclair6e581892020-03-02 15:47:43 -0500779 if (has_error())
780 return nullptr;
781 if (subtype == nullptr) {
782 set_error(peek(), "missing type for ptr declaration");
783 return nullptr;
784 }
785
786 t = next();
787 if (!t.IsGreaterThan()) {
788 set_error(t, "missing > for ptr declaration");
789 return nullptr;
790 }
791
David Netoa8cd18e2020-03-27 00:47:16 +0000792 return ctx_.type_mgr().Get(
Dan Sinclair6e581892020-03-02 15:47:43 -0500793 std::make_unique<ast::type::PointerType>(subtype, sc));
794}
795
796ast::type::Type* ParserImpl::type_decl_vector(Token t) {
797 next(); // Consume the peek
798
Greg Roth82293602020-04-06 17:16:56 +0000799 uint32_t count = 2;
Dan Sinclair6e581892020-03-02 15:47:43 -0500800 if (t.IsVec3())
801 count = 3;
802 else if (t.IsVec4())
803 count = 4;
804
805 t = next();
806 if (!t.IsLessThan()) {
807 set_error(t, "missing < for vector");
808 return nullptr;
809 }
810
Ryan Harrison0caab672020-04-15 20:47:55 +0000811 auto* subtype = type_decl();
Dan Sinclair6e581892020-03-02 15:47:43 -0500812 if (has_error())
813 return nullptr;
814 if (subtype == nullptr) {
815 set_error(peek(), "unable to determine subtype for vector");
816 return nullptr;
817 }
818
819 t = next();
820 if (!t.IsGreaterThan()) {
821 set_error(t, "missing > for vector");
822 return nullptr;
823 }
824
David Netoa8cd18e2020-03-27 00:47:16 +0000825 return ctx_.type_mgr().Get(
Dan Sinclair6e581892020-03-02 15:47:43 -0500826 std::make_unique<ast::type::VectorType>(subtype, count));
827}
828
dan sinclairc8a85aa2020-07-30 16:50:25 +0000829ast::type::Type* ParserImpl::type_decl_array(Token t, uint32_t stride) {
Dan Sinclair6e581892020-03-02 15:47:43 -0500830 next(); // Consume the peek
831
832 t = next();
833 if (!t.IsLessThan()) {
834 set_error(t, "missing < for array declaration");
835 return nullptr;
836 }
837
Ryan Harrison0caab672020-04-15 20:47:55 +0000838 auto* subtype = type_decl();
Dan Sinclair6e581892020-03-02 15:47:43 -0500839 if (has_error())
840 return nullptr;
841 if (subtype == nullptr) {
842 set_error(peek(), "invalid type for array declaration");
843 return nullptr;
844 }
845
846 t = next();
Greg Roth82293602020-04-06 17:16:56 +0000847 uint32_t size = 0;
Dan Sinclair6e581892020-03-02 15:47:43 -0500848 if (t.IsComma()) {
849 t = next();
dan sinclairc6f29472020-06-02 20:11:44 +0000850 if (!t.IsSintLiteral()) {
Dan Sinclair6e581892020-03-02 15:47:43 -0500851 set_error(t, "missing size of array declaration");
852 return nullptr;
853 }
854 if (t.to_i32() <= 0) {
855 set_error(t, "invalid size for array declaration");
856 return nullptr;
857 }
Greg Roth82293602020-04-06 17:16:56 +0000858 size = static_cast<uint32_t>(t.to_i32());
Dan Sinclair6e581892020-03-02 15:47:43 -0500859 t = next();
860 }
861 if (!t.IsGreaterThan()) {
862 set_error(t, "missing > for array declaration");
863 return nullptr;
864 }
865
dan sinclairc8a85aa2020-07-30 16:50:25 +0000866 auto ty = std::make_unique<ast::type::ArrayType>(subtype, size);
867 if (stride != 0) {
868 ty->set_array_stride(stride);
869 }
870 return ctx_.type_mgr().Get(std::move(ty));
871}
872
873// array_decoration_list
874// : ATTR_LEFT (array_decoration COMMA)* array_decoration ATTR_RIGHT
875// array_decoration
876// : STRIDE INT_LITERAL
877//
878// As there is currently only one decoration I'm combining these for now.
879// we can split apart later if needed.
880uint32_t ParserImpl::array_decoration_list() {
881 auto t = peek();
882 if (!t.IsAttrLeft()) {
883 return 0;
884 }
885 t = peek(1);
886 if (!t.IsStride()) {
887 return 0;
888 }
889
890 next(); // consume the peek of [[
891 next(); // consume the peek of stride
892
893 t = next();
894 if (!t.IsSintLiteral()) {
895 set_error(t, "missing value for stride decoration");
896 return 0;
897 }
898 if (t.to_i32() < 0) {
899 set_error(t, "invalid stride value: " + t.to_str());
900 return 0;
901 }
902
903 uint32_t stride = static_cast<uint32_t>(t.to_i32());
904 t = next();
905 if (!t.IsAttrRight()) {
906 set_error(t, "missing ]] for array decoration");
907 return 0;
908 }
909 return stride;
Dan Sinclair6e581892020-03-02 15:47:43 -0500910}
911
912ast::type::Type* ParserImpl::type_decl_matrix(Token t) {
913 next(); // Consume the peek
914
Greg Roth82293602020-04-06 17:16:56 +0000915 uint32_t rows = 2;
916 uint32_t columns = 2;
Dan Sinclair6e581892020-03-02 15:47:43 -0500917 if (t.IsMat3x2() || t.IsMat3x3() || t.IsMat3x4()) {
918 rows = 3;
919 } else if (t.IsMat4x2() || t.IsMat4x3() || t.IsMat4x4()) {
920 rows = 4;
921 }
922 if (t.IsMat2x3() || t.IsMat3x3() || t.IsMat4x3()) {
923 columns = 3;
924 } else if (t.IsMat2x4() || t.IsMat3x4() || t.IsMat4x4()) {
925 columns = 4;
926 }
927
928 t = next();
929 if (!t.IsLessThan()) {
930 set_error(t, "missing < for matrix");
931 return nullptr;
932 }
933
Ryan Harrison0caab672020-04-15 20:47:55 +0000934 auto* subtype = type_decl();
Dan Sinclair6e581892020-03-02 15:47:43 -0500935 if (has_error())
936 return nullptr;
937 if (subtype == nullptr) {
938 set_error(peek(), "unable to determine subtype for matrix");
939 return nullptr;
940 }
941
942 t = next();
943 if (!t.IsGreaterThan()) {
944 set_error(t, "missing > for matrix");
945 return nullptr;
946 }
947
David Netoa8cd18e2020-03-27 00:47:16 +0000948 return ctx_.type_mgr().Get(
Dan Sinclair6e581892020-03-02 15:47:43 -0500949 std::make_unique<ast::type::MatrixType>(subtype, rows, columns));
950}
951
952// storage_class
953// : INPUT
954// | OUTPUT
955// | UNIFORM
956// | WORKGROUP
957// | UNIFORM_CONSTANT
958// | STORAGE_BUFFER
959// | IMAGE
Dan Sinclair6e581892020-03-02 15:47:43 -0500960// | PRIVATE
961// | FUNCTION
962ast::StorageClass ParserImpl::storage_class() {
963 auto t = peek();
964 if (t.IsIn()) {
965 next(); // consume the peek
966 return ast::StorageClass::kInput;
967 }
968 if (t.IsOut()) {
969 next(); // consume the peek
970 return ast::StorageClass::kOutput;
971 }
972 if (t.IsUniform()) {
973 next(); // consume the peek
974 return ast::StorageClass::kUniform;
975 }
976 if (t.IsWorkgroup()) {
977 next(); // consume the peek
978 return ast::StorageClass::kWorkgroup;
979 }
980 if (t.IsUniformConstant()) {
981 next(); // consume the peek
982 return ast::StorageClass::kUniformConstant;
983 }
984 if (t.IsStorageBuffer()) {
985 next(); // consume the peek
986 return ast::StorageClass::kStorageBuffer;
987 }
988 if (t.IsImage()) {
989 next(); // consume the peek
990 return ast::StorageClass::kImage;
991 }
Dan Sinclair6e581892020-03-02 15:47:43 -0500992 if (t.IsPrivate()) {
993 next(); // consume the peek
994 return ast::StorageClass::kPrivate;
995 }
996 if (t.IsFunction()) {
997 next(); // consume the peek
998 return ast::StorageClass::kFunction;
999 }
1000 return ast::StorageClass::kNone;
1001}
1002
1003// struct_decl
1004// : struct_decoration_decl? STRUCT struct_body_decl
1005std::unique_ptr<ast::type::StructType> ParserImpl::struct_decl() {
1006 auto t = peek();
1007 auto source = t.source();
1008
1009 auto deco = struct_decoration_decl();
1010 if (has_error())
1011 return nullptr;
1012
1013 t = next();
1014 if (!t.IsStruct()) {
1015 set_error(t, "missing struct declaration");
1016 return nullptr;
1017 }
1018
1019 t = peek();
dan sinclair4dfda012020-05-07 19:47:39 +00001020 if (!t.IsBraceLeft()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001021 set_error(t, "missing { for struct declaration");
1022 return nullptr;
1023 }
1024
1025 auto body = struct_body_decl();
1026 if (has_error()) {
1027 return nullptr;
1028 }
1029
1030 return std::make_unique<ast::type::StructType>(
1031 std::make_unique<ast::Struct>(source, deco, std::move(body)));
1032}
1033
1034// struct_decoration_decl
1035// : ATTR_LEFT struct_decoration ATTR_RIGHT
1036ast::StructDecoration ParserImpl::struct_decoration_decl() {
1037 auto t = peek();
1038 if (!t.IsAttrLeft())
1039 return ast::StructDecoration::kNone;
1040
dan sinclairc8a85aa2020-07-30 16:50:25 +00001041 auto deco = struct_decoration(peek(1));
Dan Sinclair6e581892020-03-02 15:47:43 -05001042 if (has_error())
1043 return ast::StructDecoration::kNone;
1044 if (deco == ast::StructDecoration::kNone) {
dan sinclairc8a85aa2020-07-30 16:50:25 +00001045 return deco;
Dan Sinclair6e581892020-03-02 15:47:43 -05001046 }
1047
dan sinclairc8a85aa2020-07-30 16:50:25 +00001048 next(); // Consume the peek of [[
1049 next(); // Consume the peek from the struct_decoration
1050
Dan Sinclair6e581892020-03-02 15:47:43 -05001051 t = next();
1052 if (!t.IsAttrRight()) {
1053 set_error(t, "missing ]] for struct decoration");
1054 return ast::StructDecoration::kNone;
1055 }
1056
1057 return deco;
1058}
1059
1060// struct_decoration
1061// : BLOCK
dan sinclairc8a85aa2020-07-30 16:50:25 +00001062ast::StructDecoration ParserImpl::struct_decoration(Token t) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001063 if (t.IsBlock()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001064 return ast::StructDecoration::kBlock;
1065 }
1066 return ast::StructDecoration::kNone;
1067}
1068
1069// struct_body_decl
1070// : BRACKET_LEFT struct_member* BRACKET_RIGHT
dan sinclair3ffec802020-04-06 19:37:37 +00001071ast::StructMemberList ParserImpl::struct_body_decl() {
Dan Sinclair6e581892020-03-02 15:47:43 -05001072 auto t = peek();
dan sinclair4dfda012020-05-07 19:47:39 +00001073 if (!t.IsBraceLeft())
Dan Sinclair6e581892020-03-02 15:47:43 -05001074 return {};
1075
1076 next(); // Consume the peek
1077
1078 t = peek();
dan sinclair4dfda012020-05-07 19:47:39 +00001079 if (t.IsBraceRight())
Dan Sinclair6e581892020-03-02 15:47:43 -05001080 return {};
1081
dan sinclair3ffec802020-04-06 19:37:37 +00001082 ast::StructMemberList members;
Dan Sinclair6e581892020-03-02 15:47:43 -05001083 for (;;) {
1084 auto mem = struct_member();
1085 if (has_error())
1086 return {};
1087 if (mem == nullptr) {
1088 set_error(peek(), "invalid struct member");
1089 return {};
1090 }
1091
1092 members.push_back(std::move(mem));
1093
1094 t = peek();
dan sinclair4dfda012020-05-07 19:47:39 +00001095 if (t.IsBraceRight() || t.IsEof())
Dan Sinclair6e581892020-03-02 15:47:43 -05001096 break;
1097 }
1098
1099 t = next();
dan sinclair4dfda012020-05-07 19:47:39 +00001100 if (!t.IsBraceRight()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001101 set_error(t, "missing } for struct declaration");
1102 return {};
1103 }
1104
1105 return members;
1106}
1107
1108// struct_member
1109// : struct_member_decoration_decl variable_ident_decl SEMICOLON
1110std::unique_ptr<ast::StructMember> ParserImpl::struct_member() {
1111 auto t = peek();
1112 auto source = t.source();
1113
1114 auto decos = struct_member_decoration_decl();
1115 if (has_error())
1116 return nullptr;
1117
1118 std::string name;
1119 ast::type::Type* type;
1120 std::tie(name, type) = variable_ident_decl();
1121 if (has_error())
1122 return nullptr;
dan sinclairf26d9a82020-03-26 15:31:36 +00001123 if (name.empty() || type == nullptr) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001124 set_error(peek(), "invalid identifier declaration");
1125 return nullptr;
1126 }
1127
1128 t = next();
1129 if (!t.IsSemicolon()) {
1130 set_error(t, "missing ; for struct member");
1131 return nullptr;
1132 }
1133
1134 return std::make_unique<ast::StructMember>(source, name, type,
1135 std::move(decos));
1136}
1137
1138// struct_member_decoration_decl
1139// :
1140// | ATTR_LEFT (struct_member_decoration COMMA)*
1141// struct_member_decoration ATTR_RIGHT
dan sinclair3ffec802020-04-06 19:37:37 +00001142ast::StructMemberDecorationList ParserImpl::struct_member_decoration_decl() {
Dan Sinclair6e581892020-03-02 15:47:43 -05001143 auto t = peek();
1144 if (!t.IsAttrLeft())
1145 return {};
1146
1147 next(); // Consume the peek
1148
1149 t = peek();
1150 if (t.IsAttrRight()) {
1151 set_error(t, "empty struct member decoration found");
1152 return {};
1153 }
1154
dan sinclair3ffec802020-04-06 19:37:37 +00001155 ast::StructMemberDecorationList decos;
Dan Sinclair6e581892020-03-02 15:47:43 -05001156 bool found_offset = false;
1157 for (;;) {
1158 auto deco = struct_member_decoration();
1159 if (has_error())
1160 return {};
1161 if (deco == nullptr)
1162 break;
1163
1164 if (deco->IsOffset()) {
1165 if (found_offset) {
1166 set_error(peek(), "duplicate offset decoration found");
1167 return {};
1168 }
1169 found_offset = true;
1170 }
1171 decos.push_back(std::move(deco));
1172
1173 t = next();
1174 if (!t.IsComma())
1175 break;
1176 }
1177
1178 if (!t.IsAttrRight()) {
1179 set_error(t, "missing ]] for struct member decoration");
1180 return {};
1181 }
1182 return decos;
1183}
1184
1185// struct_member_decoration
1186// : OFFSET INT_LITERAL
1187std::unique_ptr<ast::StructMemberDecoration>
1188ParserImpl::struct_member_decoration() {
1189 auto t = peek();
1190 if (!t.IsOffset())
1191 return nullptr;
1192
1193 next(); // Consume the peek
1194
1195 t = next();
dan sinclairc6f29472020-06-02 20:11:44 +00001196 if (!t.IsSintLiteral()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001197 set_error(t, "invalid value for offset decoration");
1198 return nullptr;
1199 }
1200 int32_t val = t.to_i32();
1201 if (val < 0) {
1202 set_error(t, "offset value must be >= 0");
1203 return nullptr;
1204 }
1205
Greg Roth82293602020-04-06 17:16:56 +00001206 return std::make_unique<ast::StructMemberOffsetDecoration>(val);
Dan Sinclair6e581892020-03-02 15:47:43 -05001207}
1208
1209// function_decl
1210// : function_header body_stmt
1211std::unique_ptr<ast::Function> ParserImpl::function_decl() {
1212 auto f = function_header();
1213 if (has_error())
1214 return nullptr;
1215 if (f == nullptr)
1216 return nullptr;
1217
1218 auto body = body_stmt();
1219 if (has_error())
1220 return nullptr;
1221
1222 f->set_body(std::move(body));
1223 return f;
1224}
1225
1226// function_type_decl
1227// : type_decl
1228// | VOID
1229ast::type::Type* ParserImpl::function_type_decl() {
Dan Sinclair6e581892020-03-02 15:47:43 -05001230 auto t = peek();
1231 if (t.IsVoid()) {
1232 next(); // Consume the peek
David Netoa8cd18e2020-03-27 00:47:16 +00001233 return ctx_.type_mgr().Get(std::make_unique<ast::type::VoidType>());
Dan Sinclair6e581892020-03-02 15:47:43 -05001234 }
1235 return type_decl();
1236}
1237
1238// function_header
1239// : FN IDENT PAREN_LEFT param_list PAREN_RIGHT ARROW function_type_decl
1240std::unique_ptr<ast::Function> ParserImpl::function_header() {
1241 auto t = peek();
1242 if (!t.IsFn())
1243 return nullptr;
1244
1245 auto source = t.source();
1246 next(); // Consume the peek
1247
1248 t = next();
1249 if (!t.IsIdentifier()) {
1250 set_error(t, "missing identifier for function");
1251 return nullptr;
1252 }
1253 auto name = t.to_str();
1254
1255 t = next();
1256 if (!t.IsParenLeft()) {
1257 set_error(t, "missing ( for function declaration");
1258 return nullptr;
1259 }
1260
1261 auto params = param_list();
1262 if (has_error())
1263 return nullptr;
1264
1265 t = next();
1266 if (!t.IsParenRight()) {
1267 set_error(t, "missing ) for function declaration");
1268 return nullptr;
1269 }
1270
1271 t = next();
1272 if (!t.IsArrow()) {
1273 set_error(t, "missing -> for function declaration");
1274 return nullptr;
1275 }
1276
Ryan Harrison0caab672020-04-15 20:47:55 +00001277 auto* type = function_type_decl();
Dan Sinclair6e581892020-03-02 15:47:43 -05001278 if (has_error())
1279 return nullptr;
1280 if (type == nullptr) {
1281 set_error(peek(), "unable to determine function return type");
1282 return nullptr;
1283 }
1284
1285 return std::make_unique<ast::Function>(source, name, std::move(params), type);
1286}
1287
1288// param_list
1289// :
1290// | (variable_ident_decl COMMA)* variable_ident_decl
dan sinclair3ffec802020-04-06 19:37:37 +00001291ast::VariableList ParserImpl::param_list() {
Dan Sinclair6e581892020-03-02 15:47:43 -05001292 auto t = peek();
1293 auto source = t.source();
1294
dan sinclair3ffec802020-04-06 19:37:37 +00001295 ast::VariableList ret;
Dan Sinclair6e581892020-03-02 15:47:43 -05001296
1297 std::string name;
1298 ast::type::Type* type;
1299 std::tie(name, type) = variable_ident_decl();
1300 if (has_error())
1301 return {};
dan sinclairf26d9a82020-03-26 15:31:36 +00001302 if (name.empty() || type == nullptr)
Dan Sinclair6e581892020-03-02 15:47:43 -05001303 return {};
1304
1305 for (;;) {
1306 ret.push_back(std::make_unique<ast::Variable>(
1307 source, name, ast::StorageClass::kNone, type));
1308
1309 t = peek();
1310 if (!t.IsComma())
1311 break;
1312
1313 source = t.source();
1314 next(); // Consume the peek
1315
1316 std::tie(name, type) = variable_ident_decl();
1317 if (has_error())
1318 return {};
dan sinclairf26d9a82020-03-26 15:31:36 +00001319 if (name.empty() || type == nullptr) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001320 set_error(t, "found , but no variable declaration");
1321 return {};
1322 }
1323 }
1324
1325 return ret;
1326}
1327
1328// entry_point_decl
1329// : ENTRY_POINT pipeline_stage EQUAL IDENT
1330// | ENTRY_POINT pipeline_stage AS STRING_LITERAL EQUAL IDENT
1331// | ENTRY_POINT pipeline_stage AS IDENT EQUAL IDENT
1332std::unique_ptr<ast::EntryPoint> ParserImpl::entry_point_decl() {
1333 auto t = peek();
1334 auto source = t.source();
1335 if (!t.IsEntryPoint())
1336 return nullptr;
1337
1338 next(); // Consume the peek
1339
1340 auto stage = pipeline_stage();
1341 if (has_error())
1342 return nullptr;
1343 if (stage == ast::PipelineStage::kNone) {
1344 set_error(peek(), "missing pipeline stage for entry point");
1345 return nullptr;
1346 }
1347
1348 t = next();
1349 std::string name;
1350 if (t.IsAs()) {
1351 t = next();
1352 if (t.IsStringLiteral()) {
1353 name = t.to_str();
1354 } else if (t.IsIdentifier()) {
1355 name = t.to_str();
1356 } else {
1357 set_error(t, "invalid name for entry point");
1358 return nullptr;
1359 }
1360 t = next();
1361 }
1362
1363 if (!t.IsEqual()) {
1364 set_error(t, "missing = for entry point");
1365 return nullptr;
1366 }
1367
1368 t = next();
1369 if (!t.IsIdentifier()) {
1370 set_error(t, "invalid function name for entry point");
1371 return nullptr;
1372 }
1373 auto fn_name = t.to_str();
1374
1375 // Set the name to the function name if it isn't provided
1376 if (name.length() == 0)
1377 name = fn_name;
1378
1379 return std::make_unique<ast::EntryPoint>(source, stage, name, fn_name);
1380}
1381
1382// pipeline_stage
1383// : VERTEX
1384// | FRAGMENT
1385// | COMPUTE
1386ast::PipelineStage ParserImpl::pipeline_stage() {
1387 auto t = peek();
1388 if (t.IsVertex()) {
1389 next(); // consume the peek
1390 return ast::PipelineStage::kVertex;
1391 }
1392 if (t.IsFragment()) {
1393 next(); // consume the peek
1394 return ast::PipelineStage::kFragment;
1395 }
1396 if (t.IsCompute()) {
1397 next(); // consume the peek
1398 return ast::PipelineStage::kCompute;
1399 }
1400 return ast::PipelineStage::kNone;
1401}
1402
1403// body_stmt
1404// : BRACKET_LEFT statements BRACKET_RIGHT
dan sinclairf7515012020-07-27 15:25:00 +00001405std::unique_ptr<ast::BlockStatement> ParserImpl::body_stmt() {
Dan Sinclair6e581892020-03-02 15:47:43 -05001406 auto t = peek();
dan sinclair4dfda012020-05-07 19:47:39 +00001407 if (!t.IsBraceLeft())
Dan Sinclair6e581892020-03-02 15:47:43 -05001408 return {};
1409
1410 next(); // Consume the peek
1411
1412 auto stmts = statements();
1413 if (has_error())
1414 return {};
1415
1416 t = next();
dan sinclair4dfda012020-05-07 19:47:39 +00001417 if (!t.IsBraceRight()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001418 set_error(t, "missing }");
1419 return {};
1420 }
1421
1422 return stmts;
1423}
1424
1425// paren_rhs_stmt
1426// : PAREN_LEFT logical_or_expression PAREN_RIGHT
1427std::unique_ptr<ast::Expression> ParserImpl::paren_rhs_stmt() {
1428 auto t = peek();
1429 if (!t.IsParenLeft()) {
1430 set_error(t, "expected (");
1431 return nullptr;
1432 }
1433 next(); // Consume the peek
1434
1435 auto expr = logical_or_expression();
1436 if (has_error())
1437 return nullptr;
1438 if (expr == nullptr) {
1439 set_error(peek(), "unable to parse expression");
1440 return nullptr;
1441 }
1442
1443 t = next();
1444 if (!t.IsParenRight()) {
1445 set_error(t, "expected )");
1446 return nullptr;
1447 }
1448
1449 return expr;
1450}
1451
1452// statements
1453// : statement*
dan sinclairf7515012020-07-27 15:25:00 +00001454std::unique_ptr<ast::BlockStatement> ParserImpl::statements() {
1455 auto ret = std::make_unique<ast::BlockStatement>();
Dan Sinclair6e581892020-03-02 15:47:43 -05001456
1457 for (;;) {
1458 auto stmt = statement();
1459 if (has_error())
1460 return {};
1461 if (stmt == nullptr)
1462 break;
1463
dan sinclairf7515012020-07-27 15:25:00 +00001464 ret->append(std::move(stmt));
Dan Sinclair6e581892020-03-02 15:47:43 -05001465 }
1466
1467 return ret;
1468}
1469
1470// statement
1471// : SEMICOLON
dan sinclair091b2b52020-06-01 13:44:06 +00001472// | return_stmt SEMICOLON
Dan Sinclair6e581892020-03-02 15:47:43 -05001473// | if_stmt
Dan Sinclair6e581892020-03-02 15:47:43 -05001474// | switch_stmt
1475// | loop_stmt
Tomek Ponitka63a5aa72020-08-24 18:22:22 +00001476// | for_stmt
dan sinclairfbbc6172020-07-21 15:13:36 +00001477// | func_call_stmt SEMICOLON
Dan Sinclair6e581892020-03-02 15:47:43 -05001478// | variable_stmt SEMICOLON
1479// | break_stmt SEMICOLON
1480// | continue_stmt SEMICOLON
dan sinclairf75f2cd2020-07-25 14:33:13 +00001481// | DISCARD SEMICOLON
dan sinclair091b2b52020-06-01 13:44:06 +00001482// | assignment_stmt SEMICOLON
Tomek Ponitka43c2a6c2020-08-24 13:43:16 +00001483// | body_stmt
Dan Sinclair6e581892020-03-02 15:47:43 -05001484std::unique_ptr<ast::Statement> ParserImpl::statement() {
1485 auto t = peek();
1486 if (t.IsSemicolon()) {
1487 next(); // Consume the peek
1488 return statement();
1489 }
1490
dan sinclair091b2b52020-06-01 13:44:06 +00001491 auto ret_stmt = return_stmt();
1492 if (has_error())
1493 return nullptr;
1494 if (ret_stmt != nullptr) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001495 t = next();
1496 if (!t.IsSemicolon()) {
1497 set_error(t, "missing ;");
1498 return nullptr;
1499 }
dan sinclair091b2b52020-06-01 13:44:06 +00001500 return ret_stmt;
Dan Sinclair6e581892020-03-02 15:47:43 -05001501 }
1502
1503 auto stmt_if = if_stmt();
1504 if (has_error())
1505 return nullptr;
1506 if (stmt_if != nullptr)
1507 return stmt_if;
1508
Dan Sinclair6e581892020-03-02 15:47:43 -05001509 auto sw = switch_stmt();
1510 if (has_error())
1511 return nullptr;
1512 if (sw != nullptr)
1513 return sw;
1514
1515 auto loop = loop_stmt();
1516 if (has_error())
1517 return nullptr;
1518 if (loop != nullptr)
1519 return loop;
1520
Tomek Ponitka63a5aa72020-08-24 18:22:22 +00001521 auto stmt_for = for_stmt();
1522 if (has_error())
1523 return nullptr;
1524 if (stmt_for != nullptr)
1525 return stmt_for;
1526
dan sinclairfbbc6172020-07-21 15:13:36 +00001527 auto func = func_call_stmt();
1528 if (has_error())
1529 return nullptr;
1530 if (func != nullptr) {
1531 t = next();
1532 if (!t.IsSemicolon()) {
1533 set_error(t, "missing ;");
1534 return nullptr;
1535 }
1536 return func;
1537 }
1538
Dan Sinclair6e581892020-03-02 15:47:43 -05001539 auto var = variable_stmt();
1540 if (has_error())
1541 return nullptr;
1542 if (var != nullptr) {
1543 t = next();
1544 if (!t.IsSemicolon()) {
1545 set_error(t, "missing ;");
1546 return nullptr;
1547 }
1548 return var;
1549 }
1550
1551 auto b = break_stmt();
1552 if (has_error())
1553 return nullptr;
1554 if (b != nullptr) {
1555 t = next();
1556 if (!t.IsSemicolon()) {
1557 set_error(t, "missing ;");
1558 return nullptr;
1559 }
1560 return b;
1561 }
1562
1563 auto cont = continue_stmt();
1564 if (has_error())
1565 return nullptr;
1566 if (cont != nullptr) {
1567 t = next();
1568 if (!t.IsSemicolon()) {
1569 set_error(t, "missing ;");
1570 return nullptr;
1571 }
1572 return cont;
1573 }
1574
dan sinclairf75f2cd2020-07-25 14:33:13 +00001575 if (t.IsDiscard()) {
1576 auto source = t.source();
1577 next(); // Consume the peek
1578
1579 t = next();
1580 if (!t.IsSemicolon()) {
1581 set_error(t, "missing ;");
1582 return nullptr;
1583 }
1584 return std::make_unique<ast::DiscardStatement>(source);
1585 }
1586
Dan Sinclair6e581892020-03-02 15:47:43 -05001587 auto assign = assignment_stmt();
1588 if (has_error())
1589 return nullptr;
1590 if (assign != nullptr) {
1591 t = next();
1592 if (!t.IsSemicolon()) {
1593 set_error(t, "missing ;");
1594 return nullptr;
1595 }
1596 return assign;
1597 }
1598
Tomek Ponitka43c2a6c2020-08-24 13:43:16 +00001599 auto body = body_stmt();
1600 if (has_error())
1601 return nullptr;
1602 if (body != nullptr)
1603 return body;
1604
Dan Sinclair6e581892020-03-02 15:47:43 -05001605 return nullptr;
1606}
1607
dan sinclair091b2b52020-06-01 13:44:06 +00001608// return_stmt
1609// : RETURN logical_or_expression?
1610std::unique_ptr<ast::ReturnStatement> ParserImpl::return_stmt() {
Dan Sinclair6e581892020-03-02 15:47:43 -05001611 auto t = peek();
dan sinclair091b2b52020-06-01 13:44:06 +00001612 if (!t.IsReturn())
Dan Sinclair6e581892020-03-02 15:47:43 -05001613 return nullptr;
1614
1615 auto source = t.source();
1616 next(); // Consume the peek
1617
dan sinclair091b2b52020-06-01 13:44:06 +00001618 std::unique_ptr<ast::Expression> expr = nullptr;
Dan Sinclair6e581892020-03-02 15:47:43 -05001619 t = peek();
dan sinclair091b2b52020-06-01 13:44:06 +00001620 if (!t.IsSemicolon()) {
1621 expr = logical_or_expression();
Dan Sinclair6e581892020-03-02 15:47:43 -05001622 if (has_error())
1623 return nullptr;
Dan Sinclair6e581892020-03-02 15:47:43 -05001624 }
dan sinclair091b2b52020-06-01 13:44:06 +00001625 return std::make_unique<ast::ReturnStatement>(source, std::move(expr));
Dan Sinclair6e581892020-03-02 15:47:43 -05001626}
1627
1628// variable_stmt
1629// : variable_decl
1630// | variable_decl EQUAL logical_or_expression
1631// | CONST variable_ident_decl EQUAL logical_or_expression
dan sinclaire49bd5e2020-03-30 22:46:48 +00001632std::unique_ptr<ast::VariableDeclStatement> ParserImpl::variable_stmt() {
Dan Sinclair6e581892020-03-02 15:47:43 -05001633 auto t = peek();
1634 auto source = t.source();
1635 if (t.IsConst()) {
1636 next(); // Consume the peek
1637
1638 std::string name;
1639 ast::type::Type* type;
1640 std::tie(name, type) = variable_ident_decl();
1641 if (has_error())
1642 return nullptr;
dan sinclairf26d9a82020-03-26 15:31:36 +00001643 if (name.empty() || type == nullptr) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001644 set_error(peek(), "unable to parse variable declaration");
1645 return nullptr;
1646 }
1647
1648 t = next();
1649 if (!t.IsEqual()) {
1650 set_error(t, "missing = for constant declaration");
1651 return nullptr;
1652 }
1653
dan sinclaira322f5d2020-03-30 22:46:06 +00001654 auto constructor = logical_or_expression();
Dan Sinclair6e581892020-03-02 15:47:43 -05001655 if (has_error())
1656 return nullptr;
dan sinclaira322f5d2020-03-30 22:46:06 +00001657 if (constructor == nullptr) {
1658 set_error(peek(), "missing constructor for const declaration");
Dan Sinclair6e581892020-03-02 15:47:43 -05001659 return nullptr;
1660 }
1661
1662 auto var = std::make_unique<ast::Variable>(source, name,
1663 ast::StorageClass::kNone, type);
1664 var->set_is_const(true);
dan sinclaira322f5d2020-03-30 22:46:06 +00001665 var->set_constructor(std::move(constructor));
Dan Sinclair6e581892020-03-02 15:47:43 -05001666
dan sinclaire49bd5e2020-03-30 22:46:48 +00001667 return std::make_unique<ast::VariableDeclStatement>(source, std::move(var));
Dan Sinclair6e581892020-03-02 15:47:43 -05001668 }
1669
1670 auto var = variable_decl();
1671 if (has_error())
1672 return nullptr;
1673 if (var == nullptr)
1674 return nullptr;
1675
1676 t = peek();
1677 if (t.IsEqual()) {
1678 next(); // Consume the peek
dan sinclaira322f5d2020-03-30 22:46:06 +00001679 auto constructor = logical_or_expression();
Dan Sinclair6e581892020-03-02 15:47:43 -05001680 if (has_error())
1681 return nullptr;
dan sinclaira322f5d2020-03-30 22:46:06 +00001682 if (constructor == nullptr) {
1683 set_error(peek(), "missing constructor for variable declaration");
Dan Sinclair6e581892020-03-02 15:47:43 -05001684 return nullptr;
1685 }
dan sinclaira322f5d2020-03-30 22:46:06 +00001686 var->set_constructor(std::move(constructor));
Dan Sinclair6e581892020-03-02 15:47:43 -05001687 }
1688
dan sinclaire49bd5e2020-03-30 22:46:48 +00001689 return std::make_unique<ast::VariableDeclStatement>(source, std::move(var));
Dan Sinclair6e581892020-03-02 15:47:43 -05001690}
1691
1692// if_stmt
dan sinclair091b2b52020-06-01 13:44:06 +00001693// : IF paren_rhs_stmt body_stmt elseif_stmt? else_stmt?
Dan Sinclair6e581892020-03-02 15:47:43 -05001694std::unique_ptr<ast::IfStatement> ParserImpl::if_stmt() {
1695 auto t = peek();
1696 if (!t.IsIf())
1697 return nullptr;
1698
1699 auto source = t.source();
1700 next(); // Consume the peek
1701
1702 auto condition = paren_rhs_stmt();
1703 if (has_error())
1704 return nullptr;
1705 if (condition == nullptr) {
1706 set_error(peek(), "unable to parse if condition");
1707 return nullptr;
1708 }
1709
1710 t = peek();
dan sinclair4dfda012020-05-07 19:47:39 +00001711 if (!t.IsBraceLeft()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001712 set_error(t, "missing {");
1713 return nullptr;
1714 }
1715
1716 auto body = body_stmt();
1717 if (has_error())
1718 return nullptr;
1719
1720 auto elseif = elseif_stmt();
1721 if (has_error())
1722 return nullptr;
1723
1724 auto el = else_stmt();
1725 if (has_error())
1726 return nullptr;
1727
1728 auto stmt = std::make_unique<ast::IfStatement>(source, std::move(condition),
1729 std::move(body));
1730 if (el != nullptr) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001731 elseif.push_back(std::move(el));
1732 }
1733 stmt->set_else_statements(std::move(elseif));
1734
1735 return stmt;
1736}
1737
1738// elseif_stmt
1739// : ELSE_IF paren_rhs_stmt body_stmt elseif_stmt?
dan sinclair3ffec802020-04-06 19:37:37 +00001740ast::ElseStatementList ParserImpl::elseif_stmt() {
Dan Sinclair6e581892020-03-02 15:47:43 -05001741 auto t = peek();
1742 if (!t.IsElseIf())
1743 return {};
1744
dan sinclair3ffec802020-04-06 19:37:37 +00001745 ast::ElseStatementList ret;
Dan Sinclair6e581892020-03-02 15:47:43 -05001746 for (;;) {
1747 auto source = t.source();
1748 next(); // Consume the peek
1749
1750 auto condition = paren_rhs_stmt();
1751 if (has_error())
1752 return {};
1753 if (condition == nullptr) {
1754 set_error(peek(), "unable to parse condition expression");
1755 return {};
1756 }
1757
1758 t = peek();
dan sinclair4dfda012020-05-07 19:47:39 +00001759 if (!t.IsBraceLeft()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001760 set_error(t, "missing {");
1761 return {};
1762 }
1763
1764 auto body = body_stmt();
1765 if (has_error())
1766 return {};
1767
1768 ret.push_back(std::make_unique<ast::ElseStatement>(
1769 source, std::move(condition), std::move(body)));
1770
1771 t = peek();
1772 if (!t.IsElseIf())
1773 break;
1774 }
1775
1776 return ret;
1777}
1778
1779// else_stmt
1780// : ELSE body_stmt
1781std::unique_ptr<ast::ElseStatement> ParserImpl::else_stmt() {
1782 auto t = peek();
1783 if (!t.IsElse())
1784 return nullptr;
1785
1786 auto source = t.source();
1787 next(); // Consume the peek
1788
1789 t = peek();
dan sinclair4dfda012020-05-07 19:47:39 +00001790 if (!t.IsBraceLeft()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001791 set_error(t, "missing {");
1792 return nullptr;
1793 }
1794
1795 auto body = body_stmt();
1796 if (has_error())
1797 return nullptr;
1798
1799 return std::make_unique<ast::ElseStatement>(source, std::move(body));
1800}
1801
Dan Sinclair6e581892020-03-02 15:47:43 -05001802// switch_stmt
1803// : SWITCH paren_rhs_stmt BRACKET_LEFT switch_body+ BRACKET_RIGHT
1804std::unique_ptr<ast::SwitchStatement> ParserImpl::switch_stmt() {
1805 auto t = peek();
1806 if (!t.IsSwitch())
1807 return nullptr;
1808
1809 auto source = t.source();
1810 next(); // Consume the peek
1811
1812 auto condition = paren_rhs_stmt();
1813 if (has_error())
1814 return nullptr;
1815 if (condition == nullptr) {
1816 set_error(peek(), "unable to parse switch expression");
1817 return nullptr;
1818 }
1819
1820 t = next();
dan sinclair4dfda012020-05-07 19:47:39 +00001821 if (!t.IsBraceLeft()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001822 set_error(t, "missing { for switch statement");
1823 return nullptr;
1824 }
1825
dan sinclair3ffec802020-04-06 19:37:37 +00001826 ast::CaseStatementList body;
Dan Sinclair6e581892020-03-02 15:47:43 -05001827 for (;;) {
1828 auto stmt = switch_body();
1829 if (has_error())
1830 return nullptr;
1831 if (stmt == nullptr)
1832 break;
1833
1834 body.push_back(std::move(stmt));
1835 }
1836
1837 t = next();
dan sinclair4dfda012020-05-07 19:47:39 +00001838 if (!t.IsBraceRight()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001839 set_error(t, "missing } for switch statement");
1840 return nullptr;
1841 }
1842 return std::make_unique<ast::SwitchStatement>(source, std::move(condition),
1843 std::move(body));
1844}
1845
1846// switch_body
dan sinclair1aadbd42020-06-01 16:56:46 +00001847// : CASE case_selectors COLON BRACKET_LEFT case_body BRACKET_RIGHT
Dan Sinclair6e581892020-03-02 15:47:43 -05001848// | DEFAULT COLON BRACKET_LEFT case_body BRACKET_RIGHT
1849std::unique_ptr<ast::CaseStatement> ParserImpl::switch_body() {
1850 auto t = peek();
1851 if (!t.IsCase() && !t.IsDefault())
1852 return nullptr;
1853
1854 auto source = t.source();
1855 next(); // Consume the peek
1856
1857 auto stmt = std::make_unique<ast::CaseStatement>();
1858 stmt->set_source(source);
1859 if (t.IsCase()) {
dan sinclair1d699152020-06-02 17:18:56 +00001860 auto selectors = case_selectors();
Dan Sinclair6e581892020-03-02 15:47:43 -05001861 if (has_error())
1862 return nullptr;
dan sinclair1d699152020-06-02 17:18:56 +00001863 if (selectors.empty()) {
1864 set_error(peek(), "unable to parse case selectors");
Dan Sinclair6e581892020-03-02 15:47:43 -05001865 return nullptr;
1866 }
dan sinclair1d699152020-06-02 17:18:56 +00001867 stmt->set_selectors(std::move(selectors));
Dan Sinclair6e581892020-03-02 15:47:43 -05001868 }
1869
1870 t = next();
1871 if (!t.IsColon()) {
1872 set_error(t, "missing : for case statement");
1873 return nullptr;
1874 }
1875
1876 t = next();
dan sinclair4dfda012020-05-07 19:47:39 +00001877 if (!t.IsBraceLeft()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001878 set_error(t, "missing { for case statement");
1879 return nullptr;
1880 }
1881
1882 auto body = case_body();
1883 if (has_error())
1884 return nullptr;
1885
1886 stmt->set_body(std::move(body));
1887
1888 t = next();
dan sinclair4dfda012020-05-07 19:47:39 +00001889 if (!t.IsBraceRight()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001890 set_error(t, "missing } for case statement");
1891 return nullptr;
1892 }
1893
1894 return stmt;
1895}
1896
dan sinclair1aadbd42020-06-01 16:56:46 +00001897// case_selectors
1898// : const_literal (COMMA const_literal)*
1899ast::CaseSelectorList ParserImpl::case_selectors() {
1900 ast::CaseSelectorList selectors;
1901
1902 for (;;) {
dan sinclair579d33c2020-06-02 20:12:02 +00001903 auto t = peek();
dan sinclair1aadbd42020-06-01 16:56:46 +00001904 auto cond = const_literal();
1905 if (has_error())
1906 return {};
1907 if (cond == nullptr)
1908 break;
dan sinclair579d33c2020-06-02 20:12:02 +00001909 if (!cond->IsInt()) {
1910 set_error(t, "invalid case selector must be an integer value");
1911 return {};
1912 }
dan sinclair1aadbd42020-06-01 16:56:46 +00001913
dan sinclair579d33c2020-06-02 20:12:02 +00001914 std::unique_ptr<ast::IntLiteral> selector(cond.release()->AsInt());
1915 selectors.push_back(std::move(selector));
dan sinclair1aadbd42020-06-01 16:56:46 +00001916 }
1917
1918 return selectors;
1919}
1920
Dan Sinclair6e581892020-03-02 15:47:43 -05001921// case_body
1922// :
1923// | statement case_body
1924// | FALLTHROUGH SEMICOLON
dan sinclairf7515012020-07-27 15:25:00 +00001925std::unique_ptr<ast::BlockStatement> ParserImpl::case_body() {
1926 auto ret = std::make_unique<ast::BlockStatement>();
Dan Sinclair6e581892020-03-02 15:47:43 -05001927 for (;;) {
1928 auto t = peek();
1929 if (t.IsFallthrough()) {
1930 auto source = t.source();
1931 next(); // Consume the peek
1932
1933 t = next();
1934 if (!t.IsSemicolon()) {
1935 set_error(t, "missing ;");
1936 return {};
1937 }
1938
dan sinclairf7515012020-07-27 15:25:00 +00001939 ret->append(std::make_unique<ast::FallthroughStatement>(source));
Dan Sinclair6e581892020-03-02 15:47:43 -05001940 break;
1941 }
1942
1943 auto stmt = statement();
1944 if (has_error())
1945 return {};
1946 if (stmt == nullptr)
1947 break;
1948
dan sinclairf7515012020-07-27 15:25:00 +00001949 ret->append(std::move(stmt));
Dan Sinclair6e581892020-03-02 15:47:43 -05001950 }
1951
1952 return ret;
1953}
1954
1955// loop_stmt
1956// : LOOP BRACKET_LEFT statements continuing_stmt? BRACKET_RIGHT
1957std::unique_ptr<ast::LoopStatement> ParserImpl::loop_stmt() {
1958 auto t = peek();
1959 if (!t.IsLoop())
1960 return nullptr;
1961
1962 auto source = t.source();
1963 next(); // Consume the peek
1964
1965 t = next();
dan sinclair4dfda012020-05-07 19:47:39 +00001966 if (!t.IsBraceLeft()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001967 set_error(t, "missing { for loop");
1968 return nullptr;
1969 }
1970
1971 auto body = statements();
1972 if (has_error())
1973 return nullptr;
1974
1975 auto continuing = continuing_stmt();
1976 if (has_error())
1977 return nullptr;
1978
1979 t = next();
dan sinclair4dfda012020-05-07 19:47:39 +00001980 if (!t.IsBraceRight()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05001981 set_error(t, "missing } for loop");
1982 return nullptr;
1983 }
1984
1985 return std::make_unique<ast::LoopStatement>(source, std::move(body),
1986 std::move(continuing));
1987}
1988
Tomek Ponitka63a5aa72020-08-24 18:22:22 +00001989ForHeader::ForHeader(std::unique_ptr<ast::Statement> _initializer,
1990 std::unique_ptr<ast::Expression> _condition,
1991 std::unique_ptr<ast::Statement> _continuing)
1992 : initializer(std::move(_initializer)),
1993 condition(std::move(_condition)),
1994 continuing(std::move(_continuing)) {}
1995
1996ForHeader::~ForHeader() = default;
1997
1998// for_header
1999// : (variable_stmt | assignment_stmt | func_call_stmt)?
2000// SEMICOLON
2001// logical_or_expression? SEMICOLON
2002// (assignment_stmt | func_call_stmt)?
2003std::unique_ptr<ForHeader> ParserImpl::for_header() {
2004 std::unique_ptr<ast::Statement> initializer = nullptr;
2005 if (initializer == nullptr) {
2006 initializer = func_call_stmt();
2007 if (has_error()) {
2008 return nullptr;
2009 }
2010 }
2011 if (initializer == nullptr) {
2012 initializer = variable_stmt();
2013 if (has_error()) {
2014 return nullptr;
2015 }
2016 }
2017 if (initializer == nullptr) {
2018 initializer = assignment_stmt();
2019 if (has_error()) {
2020 return nullptr;
2021 }
2022 }
2023
2024 auto t = next();
2025 if (!t.IsSemicolon()) {
2026 set_error(t, "missing ';' after initializer in for loop");
2027 return nullptr;
2028 }
2029
2030 auto condition = logical_or_expression();
2031 if (has_error()) {
2032 return nullptr;
2033 }
2034
2035 t = next();
2036 if (!t.IsSemicolon()) {
2037 set_error(t, "missing ';' after condition in for loop");
2038 return nullptr;
2039 }
2040
2041 std::unique_ptr<ast::Statement> continuing = nullptr;
2042 if (continuing == nullptr) {
2043 continuing = func_call_stmt();
2044 if (has_error()) {
2045 return nullptr;
2046 }
2047 }
2048 if (continuing == nullptr) {
2049 continuing = assignment_stmt();
2050 if (has_error()) {
2051 return nullptr;
2052 }
2053 }
2054
2055 return std::make_unique<ForHeader>(
2056 std::move(initializer), std::move(condition), std::move(continuing));
2057}
2058
2059// for_statement
2060// : FOR PAREN_LEFT for_header PAREN_RIGHT BRACE_LEFT statements BRACE_RIGHT
2061std::unique_ptr<ast::Statement> ParserImpl::for_stmt() {
2062 auto t = peek();
2063 if (!t.IsFor())
2064 return nullptr;
2065
2066 auto source = t.source();
2067 next(); // Consume the peek
2068
2069 t = next();
2070 if (!t.IsParenLeft()) {
2071 set_error(t, "missing for loop (");
2072 return nullptr;
2073 }
2074
2075 auto header = for_header();
2076 if (has_error())
2077 return nullptr;
2078
2079 t = next();
2080 if (!t.IsParenRight()) {
2081 set_error(t, "missing for loop )");
2082 return nullptr;
2083 }
2084
2085 t = next();
2086 if (!t.IsBraceLeft()) {
2087 set_error(t, "missing for loop {");
2088 return nullptr;
2089 }
2090
2091 auto body = statements();
2092 if (has_error())
2093 return nullptr;
2094
2095 t = next();
2096 if (!t.IsBraceRight()) {
2097 set_error(t, "missing for loop }");
2098 return nullptr;
2099 }
2100
2101 // The for statement is a syntactic sugar on top of the loop statement.
2102 // We create corresponding nodes in ast with the exact same behaviour
2103 // as we would expect from the loop statement.
2104
2105 if (header->condition != nullptr) {
2106 // !condition
2107 auto not_condition = std::make_unique<ast::UnaryOpExpression>(
2108 header->condition->source(), ast::UnaryOp::kNot,
2109 std::move(header->condition));
2110 // { break; }
2111 auto break_stmt =
2112 std::make_unique<ast::BreakStatement>(not_condition->source());
2113 auto break_body =
2114 std::make_unique<ast::BlockStatement>(not_condition->source());
2115 break_body->append(std::move(break_stmt));
2116 // if (!condition) { break; }
2117 auto break_if_not_condition = std::make_unique<ast::IfStatement>(
2118 not_condition->source(), std::move(not_condition),
2119 std::move(break_body));
2120 body->insert(0, std::move(break_if_not_condition));
2121 }
2122
2123 std::unique_ptr<ast::BlockStatement> continuing_body = nullptr;
2124 if (header->continuing != nullptr) {
2125 continuing_body =
2126 std::make_unique<ast::BlockStatement>(header->continuing->source());
2127 continuing_body->append(std::move(header->continuing));
2128 }
2129
2130 auto loop = std::make_unique<ast::LoopStatement>(source, std::move(body),
2131 std::move(continuing_body));
2132
2133 if (header->initializer != nullptr) {
2134 auto result = std::make_unique<ast::BlockStatement>(source);
2135 result->append(std::move(header->initializer));
2136 result->append(std::move(loop));
2137 return result;
2138 }
2139
2140 return loop;
2141}
2142
dan sinclairfbbc6172020-07-21 15:13:36 +00002143// func_call_stmt
2144// : IDENT PAREN_LEFT argument_expression_list* PAREN_RIGHT
2145std::unique_ptr<ast::CallStatement> ParserImpl::func_call_stmt() {
2146 auto t = peek();
2147 auto t2 = peek(1);
2148 if (!t.IsIdentifier() || !t2.IsParenLeft())
2149 return nullptr;
2150
2151 auto source = t.source();
2152
2153 next(); // Consume the peek
2154 next(); // Consume the 2nd peek
2155
2156 auto name = t.to_str();
2157
2158 t = peek();
2159 ast::ExpressionList params;
2160 if (!t.IsParenRight() && !t.IsEof()) {
2161 params = argument_expression_list();
2162 if (has_error())
2163 return nullptr;
2164 }
2165
2166 t = next();
2167 if (!t.IsParenRight()) {
2168 set_error(t, "missing ) for call statement");
2169 return nullptr;
2170 }
2171
2172 return std::make_unique<ast::CallStatement>(
2173 std::make_unique<ast::CallExpression>(
2174 source, std::make_unique<ast::IdentifierExpression>(name),
2175 std::move(params)));
2176}
2177
dan sinclair091b2b52020-06-01 13:44:06 +00002178// break_stmt
dan sinclair6bd70612020-06-03 16:11:28 +00002179// : BREAK
dan sinclair091b2b52020-06-01 13:44:06 +00002180std::unique_ptr<ast::BreakStatement> ParserImpl::break_stmt() {
2181 auto t = peek();
2182 if (!t.IsBreak())
2183 return nullptr;
2184
dan sinclair091b2b52020-06-01 13:44:06 +00002185 next(); // Consume the peek
dan sinclair6bd70612020-06-03 16:11:28 +00002186 return std::make_unique<ast::BreakStatement>(t.source());
dan sinclair091b2b52020-06-01 13:44:06 +00002187}
2188
2189// continue_stmt
dan sinclair6bd70612020-06-03 16:11:28 +00002190// : CONTINUE
dan sinclair091b2b52020-06-01 13:44:06 +00002191std::unique_ptr<ast::ContinueStatement> ParserImpl::continue_stmt() {
2192 auto t = peek();
2193 if (!t.IsContinue())
2194 return nullptr;
2195
dan sinclair091b2b52020-06-01 13:44:06 +00002196 next(); // Consume the peek
dan sinclair6bd70612020-06-03 16:11:28 +00002197 return std::make_unique<ast::ContinueStatement>(t.source());
dan sinclair091b2b52020-06-01 13:44:06 +00002198}
2199
Dan Sinclair6e581892020-03-02 15:47:43 -05002200// continuing_stmt
2201// : CONTINUING body_stmt
dan sinclairf7515012020-07-27 15:25:00 +00002202std::unique_ptr<ast::BlockStatement> ParserImpl::continuing_stmt() {
Dan Sinclair6e581892020-03-02 15:47:43 -05002203 auto t = peek();
dan sinclairf7515012020-07-27 15:25:00 +00002204 if (!t.IsContinuing()) {
2205 return std::make_unique<ast::BlockStatement>();
2206 }
Dan Sinclair6e581892020-03-02 15:47:43 -05002207
2208 next(); // Consume the peek
2209 return body_stmt();
2210}
2211
Dan Sinclair6e581892020-03-02 15:47:43 -05002212// primary_expression
2213// : (IDENT NAMESPACE)* IDENT
dan sinclair5b853ee2020-06-22 20:44:27 +00002214// | type_decl PAREN_LEFT argument_expression_list* PAREN_RIGHT
Dan Sinclair6e581892020-03-02 15:47:43 -05002215// | const_literal
2216// | paren_rhs_stmt
2217// | CAST LESS_THAN type_decl GREATER_THAN paren_rhs_stmt
2218// | AS LESS_THAN type_decl GREATER_THAN paren_rhs_stmt
2219std::unique_ptr<ast::Expression> ParserImpl::primary_expression() {
2220 auto t = peek();
2221 auto source = t.source();
2222
2223 auto lit = const_literal();
2224 if (has_error())
2225 return nullptr;
2226 if (lit != nullptr) {
dan sinclaira322f5d2020-03-30 22:46:06 +00002227 return std::make_unique<ast::ScalarConstructorExpression>(source,
2228 std::move(lit));
Dan Sinclair6e581892020-03-02 15:47:43 -05002229 }
2230
2231 t = peek();
2232 if (t.IsParenLeft()) {
2233 auto paren = paren_rhs_stmt();
2234 if (has_error())
2235 return nullptr;
2236
2237 return paren;
2238 }
2239
2240 if (t.IsCast() || t.IsAs()) {
2241 auto src = t;
2242
2243 next(); // Consume the peek
2244
2245 t = next();
2246 if (!t.IsLessThan()) {
2247 set_error(t, "missing < for " + src.to_name() + " expression");
2248 return nullptr;
2249 }
2250
Ryan Harrison0caab672020-04-15 20:47:55 +00002251 auto* type = type_decl();
Dan Sinclair6e581892020-03-02 15:47:43 -05002252 if (has_error())
2253 return nullptr;
2254 if (type == nullptr) {
2255 set_error(peek(), "missing type for " + src.to_name() + " expression");
2256 return nullptr;
2257 }
2258
2259 t = next();
2260 if (!t.IsGreaterThan()) {
2261 set_error(t, "missing > for " + src.to_name() + " expression");
2262 return nullptr;
2263 }
2264
2265 auto params = paren_rhs_stmt();
2266 if (has_error())
2267 return nullptr;
2268 if (params == nullptr) {
2269 set_error(peek(), "unable to parse parameters");
2270 return nullptr;
2271 }
2272
2273 if (src.IsCast()) {
2274 return std::make_unique<ast::CastExpression>(source, type,
2275 std::move(params));
2276 } else {
2277 return std::make_unique<ast::AsExpression>(source, type,
2278 std::move(params));
2279 }
2280
2281 } else if (t.IsIdentifier()) {
2282 next(); // Consume the peek
2283
2284 std::vector<std::string> ident;
2285 ident.push_back(t.to_str());
2286 for (;;) {
2287 t = peek();
2288 if (!t.IsNamespace())
2289 break;
2290
2291 next(); // Consume the peek
2292 t = next();
2293 if (!t.IsIdentifier()) {
2294 set_error(t, "identifier expected");
2295 return nullptr;
2296 }
2297
2298 ident.push_back(t.to_str());
2299 }
2300 return std::make_unique<ast::IdentifierExpression>(source,
2301 std::move(ident));
2302 }
2303
Ryan Harrison0caab672020-04-15 20:47:55 +00002304 auto* type = type_decl();
Dan Sinclair6e581892020-03-02 15:47:43 -05002305 if (has_error())
2306 return nullptr;
2307 if (type != nullptr) {
2308 t = next();
2309 if (!t.IsParenLeft()) {
dan sinclaira322f5d2020-03-30 22:46:06 +00002310 set_error(t, "missing ( for type constructor");
Dan Sinclair6e581892020-03-02 15:47:43 -05002311 return nullptr;
2312 }
2313
dan sinclair5b853ee2020-06-22 20:44:27 +00002314 t = peek();
2315 ast::ExpressionList params;
2316 if (!t.IsParenRight() && !t.IsEof()) {
2317 params = argument_expression_list();
2318 if (has_error())
2319 return nullptr;
2320 }
Dan Sinclair6e581892020-03-02 15:47:43 -05002321
2322 t = next();
2323 if (!t.IsParenRight()) {
dan sinclaira322f5d2020-03-30 22:46:06 +00002324 set_error(t, "missing ) for type constructor");
Dan Sinclair6e581892020-03-02 15:47:43 -05002325 return nullptr;
2326 }
dan sinclaira322f5d2020-03-30 22:46:06 +00002327 return std::make_unique<ast::TypeConstructorExpression>(source, type,
Dan Sinclair6e581892020-03-02 15:47:43 -05002328 std::move(params));
2329 }
2330 return nullptr;
2331}
2332
Dan Sinclair6e581892020-03-02 15:47:43 -05002333// postfix_expr
2334// :
2335// | BRACE_LEFT logical_or_expression BRACE_RIGHT postfix_expr
2336// | PAREN_LEFT argument_expression_list* PAREN_RIGHT postfix_expr
2337// | PERIOD IDENTIFIER postfix_expr
2338std::unique_ptr<ast::Expression> ParserImpl::postfix_expr(
2339 std::unique_ptr<ast::Expression> prefix) {
2340 std::unique_ptr<ast::Expression> expr = nullptr;
2341
2342 auto t = peek();
2343 auto source = t.source();
dan sinclair4dfda012020-05-07 19:47:39 +00002344 if (t.IsBracketLeft()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05002345 next(); // Consume the peek
2346
2347 auto param = logical_or_expression();
2348 if (has_error())
2349 return nullptr;
2350 if (param == nullptr) {
2351 set_error(peek(), "unable to parse expression inside []");
2352 return nullptr;
2353 }
2354
2355 t = next();
dan sinclair4dfda012020-05-07 19:47:39 +00002356 if (!t.IsBracketRight()) {
Dan Sinclair6e581892020-03-02 15:47:43 -05002357 set_error(t, "missing ] for array accessor");
2358 return nullptr;
2359 }
2360 expr = std::make_unique<ast::ArrayAccessorExpression>(
2361 source, std::move(prefix), std::move(param));
2362
2363 } else if (t.IsParenLeft()) {
2364 next(); // Consume the peek
2365
2366 t = peek();
dan sinclair3ffec802020-04-06 19:37:37 +00002367 ast::ExpressionList params;
Dan Sinclair6e581892020-03-02 15:47:43 -05002368 if (!t.IsParenRight() && !t.IsEof()) {
2369 params = argument_expression_list();
2370 if (has_error())
2371 return nullptr;
2372 }
2373
2374 t = next();
2375 if (!t.IsParenRight()) {
2376 set_error(t, "missing ) for call expression");
2377 return nullptr;
2378 }
2379 expr = std::make_unique<ast::CallExpression>(source, std::move(prefix),
2380 std::move(params));
2381 } else if (t.IsPeriod()) {
2382 next(); // Consume the peek
2383
2384 t = next();
2385 if (!t.IsIdentifier()) {
2386 set_error(t, "missing identifier for member accessor");
2387 return nullptr;
2388 }
2389
2390 expr = std::make_unique<ast::MemberAccessorExpression>(
2391 source, std::move(prefix),
2392 std::make_unique<ast::IdentifierExpression>(t.source(), t.to_str()));
2393 } else {
2394 return prefix;
2395 }
2396 return postfix_expr(std::move(expr));
2397}
2398
2399// postfix_expression
2400// : primary_expression postfix_expr
2401std::unique_ptr<ast::Expression> ParserImpl::postfix_expression() {
2402 auto prefix = primary_expression();
2403 if (has_error())
2404 return nullptr;
2405 if (prefix == nullptr)
2406 return nullptr;
2407
2408 return postfix_expr(std::move(prefix));
2409}
2410
dan sinclair091b2b52020-06-01 13:44:06 +00002411// argument_expression_list
2412// : (logical_or_expression COMMA)* logical_or_expression
2413ast::ExpressionList ParserImpl::argument_expression_list() {
2414 auto arg = logical_or_expression();
2415 if (has_error())
2416 return {};
2417 if (arg == nullptr) {
2418 set_error(peek(), "unable to parse argument expression");
2419 return {};
2420 }
2421
2422 ast::ExpressionList ret;
2423 ret.push_back(std::move(arg));
2424
2425 for (;;) {
2426 auto t = peek();
2427 if (!t.IsComma())
2428 break;
2429
2430 next(); // Consume the peek
2431
2432 arg = logical_or_expression();
2433 if (has_error())
2434 return {};
2435 if (arg == nullptr) {
2436 set_error(peek(), "unable to parse argument expression after comma");
2437 return {};
2438 }
2439 ret.push_back(std::move(arg));
2440 }
2441 return ret;
2442}
2443
Dan Sinclair6e581892020-03-02 15:47:43 -05002444// unary_expression
2445// : postfix_expression
2446// | MINUS unary_expression
2447// | BANG unary_expression
Dan Sinclair6e581892020-03-02 15:47:43 -05002448std::unique_ptr<ast::Expression> ParserImpl::unary_expression() {
2449 auto t = peek();
2450 auto source = t.source();
2451 if (t.IsMinus() || t.IsBang()) {
2452 auto name = t.to_name();
2453
2454 next(); // Consume the peek
2455
2456 auto op = ast::UnaryOp::kNegation;
2457 if (t.IsBang())
2458 op = ast::UnaryOp::kNot;
2459
2460 auto expr = unary_expression();
2461 if (has_error())
2462 return nullptr;
2463 if (expr == nullptr) {
2464 set_error(peek(),
2465 "unable to parse right side of " + name + " expression");
2466 return nullptr;
2467 }
2468 return std::make_unique<ast::UnaryOpExpression>(source, op,
2469 std::move(expr));
2470 }
Dan Sinclair6e581892020-03-02 15:47:43 -05002471 return postfix_expression();
2472}
2473
Dan Sinclair6e581892020-03-02 15:47:43 -05002474// multiplicative_expr
2475// :
2476// | STAR unary_expression multiplicative_expr
2477// | FORWARD_SLASH unary_expression multiplicative_expr
2478// | MODULO unary_expression multiplicative_expr
2479std::unique_ptr<ast::Expression> ParserImpl::multiplicative_expr(
2480 std::unique_ptr<ast::Expression> lhs) {
2481 auto t = peek();
2482
dan sinclair1c9b4862020-04-07 19:27:41 +00002483 ast::BinaryOp op = ast::BinaryOp::kNone;
Dan Sinclair6e581892020-03-02 15:47:43 -05002484 if (t.IsStar())
dan sinclair1c9b4862020-04-07 19:27:41 +00002485 op = ast::BinaryOp::kMultiply;
Dan Sinclair6e581892020-03-02 15:47:43 -05002486 else if (t.IsForwardSlash())
dan sinclair1c9b4862020-04-07 19:27:41 +00002487 op = ast::BinaryOp::kDivide;
Dan Sinclair6e581892020-03-02 15:47:43 -05002488 else if (t.IsMod())
dan sinclair1c9b4862020-04-07 19:27:41 +00002489 op = ast::BinaryOp::kModulo;
Dan Sinclair6e581892020-03-02 15:47:43 -05002490 else
2491 return lhs;
2492
2493 auto source = t.source();
2494 auto name = t.to_name();
2495 next(); // Consume the peek
2496
2497 auto rhs = unary_expression();
2498 if (has_error())
2499 return nullptr;
2500 if (rhs == nullptr) {
2501 set_error(peek(), "unable to parse right side of " + name + " expression");
2502 return nullptr;
2503 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002504 return multiplicative_expr(std::make_unique<ast::BinaryExpression>(
2505 source, op, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002506}
2507
2508// multiplicative_expression
2509// : unary_expression multiplicative_expr
2510std::unique_ptr<ast::Expression> ParserImpl::multiplicative_expression() {
2511 auto lhs = unary_expression();
2512 if (has_error())
2513 return nullptr;
2514 if (lhs == nullptr)
2515 return nullptr;
2516
2517 return multiplicative_expr(std::move(lhs));
2518}
2519
2520// additive_expr
2521// :
2522// | PLUS multiplicative_expression additive_expr
2523// | MINUS multiplicative_expression additive_expr
2524std::unique_ptr<ast::Expression> ParserImpl::additive_expr(
2525 std::unique_ptr<ast::Expression> lhs) {
2526 auto t = peek();
2527
dan sinclair1c9b4862020-04-07 19:27:41 +00002528 ast::BinaryOp op = ast::BinaryOp::kNone;
Dan Sinclair6e581892020-03-02 15:47:43 -05002529 if (t.IsPlus())
dan sinclair1c9b4862020-04-07 19:27:41 +00002530 op = ast::BinaryOp::kAdd;
Dan Sinclair6e581892020-03-02 15:47:43 -05002531 else if (t.IsMinus())
dan sinclair1c9b4862020-04-07 19:27:41 +00002532 op = ast::BinaryOp::kSubtract;
Dan Sinclair6e581892020-03-02 15:47:43 -05002533 else
2534 return lhs;
2535
2536 auto source = t.source();
2537 next(); // Consume the peek
2538
2539 auto rhs = multiplicative_expression();
2540 if (has_error())
2541 return nullptr;
2542 if (rhs == nullptr) {
2543 set_error(peek(), "unable to parse right side of + expression");
2544 return nullptr;
2545 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002546 return additive_expr(std::make_unique<ast::BinaryExpression>(
2547 source, op, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002548}
2549
2550// additive_expression
2551// : multiplicative_expression additive_expr
2552std::unique_ptr<ast::Expression> ParserImpl::additive_expression() {
2553 auto lhs = multiplicative_expression();
2554 if (has_error())
2555 return nullptr;
2556 if (lhs == nullptr)
2557 return nullptr;
2558
2559 return additive_expr(std::move(lhs));
2560}
2561
2562// shift_expr
2563// :
2564// | LESS_THAN LESS_THAN additive_expression shift_expr
2565// | GREATER_THAN GREATER_THAN additive_expression shift_expr
Dan Sinclair6e581892020-03-02 15:47:43 -05002566std::unique_ptr<ast::Expression> ParserImpl::shift_expr(
2567 std::unique_ptr<ast::Expression> lhs) {
2568 auto t = peek();
2569 auto source = t.source();
2570 auto t2 = peek(1);
Dan Sinclair6e581892020-03-02 15:47:43 -05002571
Ryan Harrison0caab672020-04-15 20:47:55 +00002572 auto* name = "";
dan sinclair1c9b4862020-04-07 19:27:41 +00002573 ast::BinaryOp op = ast::BinaryOp::kNone;
Dan Sinclair6e581892020-03-02 15:47:43 -05002574 if (t.IsLessThan() && t2.IsLessThan()) {
2575 next(); // Consume the t peek
2576 next(); // Consume the t2 peek
dan sinclair1c9b4862020-04-07 19:27:41 +00002577 op = ast::BinaryOp::kShiftLeft;
Dan Sinclair6e581892020-03-02 15:47:43 -05002578 name = "<<";
Dan Sinclair6e581892020-03-02 15:47:43 -05002579 } else if (t.IsGreaterThan() && t2.IsGreaterThan()) {
2580 next(); // Consume the t peek
2581 next(); // Consume the t2 peek
dan sinclair1c9b4862020-04-07 19:27:41 +00002582 op = ast::BinaryOp::kShiftRight;
Dan Sinclair6e581892020-03-02 15:47:43 -05002583 name = ">>";
2584 } else {
2585 return lhs;
2586 }
2587
2588 auto rhs = additive_expression();
2589 if (has_error())
2590 return nullptr;
2591 if (rhs == nullptr) {
2592 set_error(peek(), std::string("unable to parse right side of ") + name +
2593 " expression");
2594 return nullptr;
2595 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002596 return shift_expr(std::make_unique<ast::BinaryExpression>(
2597 source, op, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002598}
2599
2600// shift_expression
2601// : additive_expression shift_expr
2602std::unique_ptr<ast::Expression> ParserImpl::shift_expression() {
2603 auto lhs = additive_expression();
2604 if (has_error())
2605 return nullptr;
2606 if (lhs == nullptr)
2607 return nullptr;
2608
2609 return shift_expr(std::move(lhs));
2610}
2611
2612// relational_expr
2613// :
2614// | LESS_THAN shift_expression relational_expr
2615// | GREATER_THAN shift_expression relational_expr
2616// | LESS_THAN_EQUAL shift_expression relational_expr
2617// | GREATER_THAN_EQUAL shift_expression relational_expr
2618std::unique_ptr<ast::Expression> ParserImpl::relational_expr(
2619 std::unique_ptr<ast::Expression> lhs) {
2620 auto t = peek();
dan sinclair1c9b4862020-04-07 19:27:41 +00002621 ast::BinaryOp op = ast::BinaryOp::kNone;
Dan Sinclair6e581892020-03-02 15:47:43 -05002622 if (t.IsLessThan())
dan sinclair1c9b4862020-04-07 19:27:41 +00002623 op = ast::BinaryOp::kLessThan;
Dan Sinclair6e581892020-03-02 15:47:43 -05002624 else if (t.IsGreaterThan())
dan sinclair1c9b4862020-04-07 19:27:41 +00002625 op = ast::BinaryOp::kGreaterThan;
Dan Sinclair6e581892020-03-02 15:47:43 -05002626 else if (t.IsLessThanEqual())
dan sinclair1c9b4862020-04-07 19:27:41 +00002627 op = ast::BinaryOp::kLessThanEqual;
Dan Sinclair6e581892020-03-02 15:47:43 -05002628 else if (t.IsGreaterThanEqual())
dan sinclair1c9b4862020-04-07 19:27:41 +00002629 op = ast::BinaryOp::kGreaterThanEqual;
Dan Sinclair6e581892020-03-02 15:47:43 -05002630 else
2631 return lhs;
2632
2633 auto source = t.source();
2634 auto name = t.to_name();
2635 next(); // Consume the peek
2636
2637 auto rhs = shift_expression();
2638 if (has_error())
2639 return nullptr;
2640 if (rhs == nullptr) {
2641 set_error(peek(), "unable to parse right side of " + name + " expression");
2642 return nullptr;
2643 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002644 return relational_expr(std::make_unique<ast::BinaryExpression>(
2645 source, op, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002646}
2647
2648// relational_expression
2649// : shift_expression relational_expr
2650std::unique_ptr<ast::Expression> ParserImpl::relational_expression() {
2651 auto lhs = shift_expression();
2652 if (has_error())
2653 return nullptr;
2654 if (lhs == nullptr)
2655 return nullptr;
2656
2657 return relational_expr(std::move(lhs));
2658}
2659
2660// equality_expr
2661// :
2662// | EQUAL_EQUAL relational_expression equality_expr
2663// | NOT_EQUAL relational_expression equality_expr
2664std::unique_ptr<ast::Expression> ParserImpl::equality_expr(
2665 std::unique_ptr<ast::Expression> lhs) {
2666 auto t = peek();
dan sinclair1c9b4862020-04-07 19:27:41 +00002667 ast::BinaryOp op = ast::BinaryOp::kNone;
Dan Sinclair6e581892020-03-02 15:47:43 -05002668 if (t.IsEqualEqual())
dan sinclair1c9b4862020-04-07 19:27:41 +00002669 op = ast::BinaryOp::kEqual;
Dan Sinclair6e581892020-03-02 15:47:43 -05002670 else if (t.IsNotEqual())
dan sinclair1c9b4862020-04-07 19:27:41 +00002671 op = ast::BinaryOp::kNotEqual;
Dan Sinclair6e581892020-03-02 15:47:43 -05002672 else
2673 return lhs;
2674
2675 auto source = t.source();
2676 auto name = t.to_name();
2677 next(); // Consume the peek
2678
2679 auto rhs = relational_expression();
2680 if (has_error())
2681 return nullptr;
2682 if (rhs == nullptr) {
2683 set_error(peek(), "unable to parse right side of " + name + " expression");
2684 return nullptr;
2685 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002686 return equality_expr(std::make_unique<ast::BinaryExpression>(
2687 source, op, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002688}
2689
2690// equality_expression
2691// : relational_expression equality_expr
2692std::unique_ptr<ast::Expression> ParserImpl::equality_expression() {
2693 auto lhs = relational_expression();
2694 if (has_error())
2695 return nullptr;
2696 if (lhs == nullptr)
2697 return nullptr;
2698
2699 return equality_expr(std::move(lhs));
2700}
2701
2702// and_expr
2703// :
2704// | AND equality_expression and_expr
2705std::unique_ptr<ast::Expression> ParserImpl::and_expr(
2706 std::unique_ptr<ast::Expression> lhs) {
2707 auto t = peek();
2708 if (!t.IsAnd())
2709 return lhs;
2710
2711 auto source = t.source();
2712 next(); // Consume the peek
2713
2714 auto rhs = equality_expression();
2715 if (has_error())
2716 return nullptr;
2717 if (rhs == nullptr) {
2718 set_error(peek(), "unable to parse right side of & expression");
2719 return nullptr;
2720 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002721 return and_expr(std::make_unique<ast::BinaryExpression>(
2722 source, ast::BinaryOp::kAnd, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002723}
2724
2725// and_expression
2726// : equality_expression and_expr
2727std::unique_ptr<ast::Expression> ParserImpl::and_expression() {
2728 auto lhs = equality_expression();
2729 if (has_error())
2730 return nullptr;
2731 if (lhs == nullptr)
2732 return nullptr;
2733
2734 return and_expr(std::move(lhs));
2735}
2736
2737// exclusive_or_expr
2738// :
2739// | XOR and_expression exclusive_or_expr
2740std::unique_ptr<ast::Expression> ParserImpl::exclusive_or_expr(
2741 std::unique_ptr<ast::Expression> lhs) {
2742 auto t = peek();
2743 if (!t.IsXor())
2744 return lhs;
2745
2746 auto source = t.source();
2747 next(); // Consume the peek
2748
2749 auto rhs = and_expression();
2750 if (has_error())
2751 return nullptr;
2752 if (rhs == nullptr) {
2753 set_error(peek(), "unable to parse right side of ^ expression");
2754 return nullptr;
2755 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002756 return exclusive_or_expr(std::make_unique<ast::BinaryExpression>(
2757 source, ast::BinaryOp::kXor, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002758}
2759
2760// exclusive_or_expression
2761// : and_expression exclusive_or_expr
2762std::unique_ptr<ast::Expression> ParserImpl::exclusive_or_expression() {
2763 auto lhs = and_expression();
2764 if (has_error())
2765 return nullptr;
2766 if (lhs == nullptr)
2767 return nullptr;
2768
2769 return exclusive_or_expr(std::move(lhs));
2770}
2771
2772// inclusive_or_expr
2773// :
2774// | OR exclusive_or_expression inclusive_or_expr
2775std::unique_ptr<ast::Expression> ParserImpl::inclusive_or_expr(
2776 std::unique_ptr<ast::Expression> lhs) {
2777 auto t = peek();
2778 if (!t.IsOr())
2779 return lhs;
2780
2781 auto source = t.source();
2782 next(); // Consume the peek
2783
2784 auto rhs = exclusive_or_expression();
2785 if (has_error())
2786 return nullptr;
2787 if (rhs == nullptr) {
2788 set_error(peek(), "unable to parse right side of | expression");
2789 return nullptr;
2790 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002791 return inclusive_or_expr(std::make_unique<ast::BinaryExpression>(
2792 source, ast::BinaryOp::kOr, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002793}
2794
2795// inclusive_or_expression
2796// : exclusive_or_expression inclusive_or_expr
2797std::unique_ptr<ast::Expression> ParserImpl::inclusive_or_expression() {
2798 auto lhs = exclusive_or_expression();
2799 if (has_error())
2800 return nullptr;
2801 if (lhs == nullptr)
2802 return nullptr;
2803
2804 return inclusive_or_expr(std::move(lhs));
2805}
2806
2807// logical_and_expr
2808// :
2809// | AND_AND inclusive_or_expression logical_and_expr
2810std::unique_ptr<ast::Expression> ParserImpl::logical_and_expr(
2811 std::unique_ptr<ast::Expression> lhs) {
2812 auto t = peek();
2813 if (!t.IsAndAnd())
2814 return lhs;
2815
2816 auto source = t.source();
2817 next(); // Consume the peek
2818
2819 auto rhs = inclusive_or_expression();
2820 if (has_error())
2821 return nullptr;
2822 if (rhs == nullptr) {
2823 set_error(peek(), "unable to parse right side of && expression");
2824 return nullptr;
2825 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002826 return logical_and_expr(std::make_unique<ast::BinaryExpression>(
2827 source, ast::BinaryOp::kLogicalAnd, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002828}
2829
2830// logical_and_expression
2831// : inclusive_or_expression logical_and_expr
2832std::unique_ptr<ast::Expression> ParserImpl::logical_and_expression() {
2833 auto lhs = inclusive_or_expression();
2834 if (has_error())
2835 return nullptr;
2836 if (lhs == nullptr)
2837 return nullptr;
2838
2839 return logical_and_expr(std::move(lhs));
2840}
2841
2842// logical_or_expr
2843// :
2844// | OR_OR logical_and_expression logical_or_expr
2845std::unique_ptr<ast::Expression> ParserImpl::logical_or_expr(
2846 std::unique_ptr<ast::Expression> lhs) {
2847 auto t = peek();
2848 if (!t.IsOrOr())
2849 return lhs;
2850
2851 auto source = t.source();
2852 next(); // Consume the peek
2853
2854 auto rhs = logical_and_expression();
2855 if (has_error())
2856 return nullptr;
2857 if (rhs == nullptr) {
2858 set_error(peek(), "unable to parse right side of || expression");
2859 return nullptr;
2860 }
dan sinclair1c9b4862020-04-07 19:27:41 +00002861 return logical_or_expr(std::make_unique<ast::BinaryExpression>(
2862 source, ast::BinaryOp::kLogicalOr, std::move(lhs), std::move(rhs)));
Dan Sinclair6e581892020-03-02 15:47:43 -05002863}
2864
2865// logical_or_expression
2866// : logical_and_expression logical_or_expr
2867std::unique_ptr<ast::Expression> ParserImpl::logical_or_expression() {
2868 auto lhs = logical_and_expression();
2869 if (has_error())
2870 return nullptr;
2871 if (lhs == nullptr)
2872 return nullptr;
2873
2874 return logical_or_expr(std::move(lhs));
2875}
2876
2877// assignment_stmt
2878// : unary_expression EQUAL logical_or_expression
2879std::unique_ptr<ast::AssignmentStatement> ParserImpl::assignment_stmt() {
2880 auto t = peek();
2881 auto source = t.source();
2882
2883 auto lhs = unary_expression();
2884 if (has_error())
2885 return nullptr;
2886 if (lhs == nullptr)
2887 return nullptr;
2888
2889 t = next();
2890 if (!t.IsEqual()) {
2891 set_error(t, "missing = for assignment");
2892 return nullptr;
2893 }
2894
2895 auto rhs = logical_or_expression();
2896 if (has_error())
2897 return nullptr;
2898 if (rhs == nullptr) {
2899 set_error(peek(), "unable to parse right side of assignment");
2900 return nullptr;
2901 }
2902
2903 return std::make_unique<ast::AssignmentStatement>(source, std::move(lhs),
2904 std::move(rhs));
2905}
2906
dan sinclair091b2b52020-06-01 13:44:06 +00002907// const_literal
2908// : INT_LITERAL
2909// | UINT_LITERAL
2910// | FLOAT_LITERAL
2911// | TRUE
2912// | FALSE
2913std::unique_ptr<ast::Literal> ParserImpl::const_literal() {
2914 auto t = peek();
2915 if (t.IsTrue()) {
2916 next(); // Consume the peek
2917
2918 auto* type = ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>());
2919 if (!type) {
2920 return nullptr;
2921 }
2922 return std::make_unique<ast::BoolLiteral>(type, true);
2923 }
2924 if (t.IsFalse()) {
2925 next(); // Consume the peek
2926 auto* type = ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>());
2927 if (!type) {
2928 return nullptr;
2929 }
2930 return std::make_unique<ast::BoolLiteral>(type, false);
2931 }
dan sinclairc6f29472020-06-02 20:11:44 +00002932 if (t.IsSintLiteral()) {
dan sinclair091b2b52020-06-01 13:44:06 +00002933 next(); // Consume the peek
2934 auto* type = ctx_.type_mgr().Get(std::make_unique<ast::type::I32Type>());
2935 if (!type) {
2936 return nullptr;
2937 }
dan sinclairc6f29472020-06-02 20:11:44 +00002938 return std::make_unique<ast::SintLiteral>(type, t.to_i32());
dan sinclair091b2b52020-06-01 13:44:06 +00002939 }
2940 if (t.IsUintLiteral()) {
2941 next(); // Consume the peek
2942 auto* type = ctx_.type_mgr().Get(std::make_unique<ast::type::U32Type>());
2943 if (!type) {
2944 return nullptr;
2945 }
2946 return std::make_unique<ast::UintLiteral>(type, t.to_u32());
2947 }
2948 if (t.IsFloatLiteral()) {
2949 next(); // Consume the peek
2950 auto* type = ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>());
2951 if (!type) {
2952 return nullptr;
2953 }
2954 return std::make_unique<ast::FloatLiteral>(type, t.to_f32());
2955 }
2956 return nullptr;
2957}
2958
2959// const_expr
2960// : type_decl PAREN_LEFT (const_expr COMMA)? const_expr PAREN_RIGHT
2961// | const_literal
2962std::unique_ptr<ast::ConstructorExpression> ParserImpl::const_expr() {
2963 auto t = peek();
2964 auto source = t.source();
2965
2966 auto* type = type_decl();
2967 if (type != nullptr) {
2968 t = next();
2969 if (!t.IsParenLeft()) {
2970 set_error(t, "missing ( for type constructor");
2971 return nullptr;
2972 }
2973
2974 ast::ExpressionList params;
2975 auto param = const_expr();
2976 if (has_error())
2977 return nullptr;
2978 if (param == nullptr) {
2979 set_error(peek(), "unable to parse constant expression");
2980 return nullptr;
2981 }
2982 params.push_back(std::move(param));
2983 for (;;) {
2984 t = peek();
2985 if (!t.IsComma())
2986 break;
2987
2988 next(); // Consume the peek
2989
2990 param = const_expr();
2991 if (has_error())
2992 return nullptr;
2993 if (param == nullptr) {
2994 set_error(peek(), "unable to parse constant expression");
2995 return nullptr;
2996 }
2997 params.push_back(std::move(param));
2998 }
2999
3000 t = next();
3001 if (!t.IsParenRight()) {
3002 set_error(t, "missing ) for type constructor");
3003 return nullptr;
3004 }
3005 return std::make_unique<ast::TypeConstructorExpression>(source, type,
3006 std::move(params));
3007 }
3008
3009 auto lit = const_literal();
3010 if (has_error())
3011 return nullptr;
3012 if (lit == nullptr) {
3013 set_error(peek(), "unable to parse const literal");
3014 return nullptr;
3015 }
3016 return std::make_unique<ast::ScalarConstructorExpression>(source,
3017 std::move(lit));
3018}
3019
Dan Sinclair6e581892020-03-02 15:47:43 -05003020} // namespace wgsl
3021} // namespace reader
3022} // namespace tint