1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "banjo/parser.h"
6
7 namespace banjo {
8
9 // The "case" keyword is not folded into CASE_TOKEN and CASE_IDENTIFIER because
10 // doing so confuses clang-format.
11 #define CASE_TOKEN(K) \
12 Token::KindAndSubkind(K, Token::Subkind::kNone).combined()
13
14 #define CASE_IDENTIFIER(K) \
15 Token::KindAndSubkind(Token::Kind::kIdentifier, K).combined()
16
17 #define TOKEN_PRIMITIVE_TYPE_CASES \
18 case CASE_IDENTIFIER(Token::Subkind::kBool): \
19 case CASE_IDENTIFIER(Token::Subkind::kInt8): \
20 case CASE_IDENTIFIER(Token::Subkind::kInt16): \
21 case CASE_IDENTIFIER(Token::Subkind::kInt32): \
22 case CASE_IDENTIFIER(Token::Subkind::kInt64): \
23 case CASE_IDENTIFIER(Token::Subkind::kUint8): \
24 case CASE_IDENTIFIER(Token::Subkind::kUint16): \
25 case CASE_IDENTIFIER(Token::Subkind::kUint32): \
26 case CASE_IDENTIFIER(Token::Subkind::kUint64): \
27 case CASE_IDENTIFIER(Token::Subkind::kFloat32): \
28 case CASE_IDENTIFIER(Token::Subkind::kFloat64): \
29 case CASE_IDENTIFIER(Token::Subkind::kUSize): \
30 case CASE_IDENTIFIER(Token::Subkind::kISize): \
31 case CASE_IDENTIFIER(Token::Subkind::kVoidPtr)
32
33
34 #define TOKEN_TYPE_CASES \
35 TOKEN_PRIMITIVE_TYPE_CASES: \
36 case CASE_IDENTIFIER(Token::Subkind::kNone): \
37 case CASE_IDENTIFIER(Token::Subkind::kArray): \
38 case CASE_IDENTIFIER(Token::Subkind::kVector): \
39 case CASE_IDENTIFIER(Token::Subkind::kString): \
40 case CASE_IDENTIFIER(Token::Subkind::kHandle): \
41 case CASE_IDENTIFIER(Token::Subkind::kRequest)
42
43 #define TOKEN_ATTR_CASES \
44 case Token::Kind::kDocComment: \
45 case Token::Kind::kLeftSquare
46
47 #define TOKEN_LITERAL_CASES \
48 case CASE_IDENTIFIER(Token::Subkind::kTrue): \
49 case CASE_IDENTIFIER(Token::Subkind::kFalse): \
50 case CASE_TOKEN(Token::Kind::kNumericLiteral): \
51 case CASE_TOKEN(Token::Kind::kStringLiteral)
52
53 namespace {
54 enum {
55 More,
56 Done,
57 };
58 } // namespace
59
Parser(Lexer * lexer,ErrorReporter * error_reporter)60 Parser::Parser(Lexer* lexer, ErrorReporter* error_reporter)
61 : lexer_(lexer), error_reporter_(error_reporter) {
62 handle_subtype_table_ = {
63 {"process", types::HandleSubtype::kProcess},
64 {"thread", types::HandleSubtype::kThread},
65 {"vmo", types::HandleSubtype::kVmo},
66 {"channel", types::HandleSubtype::kChannel},
67 {"event", types::HandleSubtype::kEvent},
68 {"port", types::HandleSubtype::kPort},
69 {"interrupt", types::HandleSubtype::kInterrupt},
70 {"debuglog", types::HandleSubtype::kLog},
71 {"socket", types::HandleSubtype::kSocket},
72 {"resource", types::HandleSubtype::kResource},
73 {"eventpair", types::HandleSubtype::kEventpair},
74 {"job", types::HandleSubtype::kJob},
75 {"vmar", types::HandleSubtype::kVmar},
76 {"fifo", types::HandleSubtype::kFifo},
77 {"guest", types::HandleSubtype::kGuest},
78 {"timer", types::HandleSubtype::kTimer},
79 {"bti", types::HandleSubtype::kBti},
80 {"profile", types::HandleSubtype::kProfile},
81 };
82
83 last_token_ = Lex();
84 }
85
LookupHandleSubtype(const raw::Identifier * identifier,types::HandleSubtype * subtype_out)86 bool Parser::LookupHandleSubtype(const raw::Identifier* identifier,
87 types::HandleSubtype* subtype_out) {
88 auto lookup = handle_subtype_table_.find(identifier->location().data());
89 if (lookup == handle_subtype_table_.end()) {
90 return false;
91 }
92 *subtype_out = lookup->second;
93 return true;
94 }
95
Fail()96 decltype(nullptr) Parser::Fail() {
97 return Fail("found unexpected token");
98 }
99
Fail(StringView message)100 decltype(nullptr) Parser::Fail(StringView message) {
101 if (ok_) {
102 error_reporter_->ReportError(last_token_, std::move(message));
103 ok_ = false;
104 }
105 return nullptr;
106 }
107
ParseIdentifier(bool is_discarded)108 std::unique_ptr<raw::Identifier> Parser::ParseIdentifier(bool is_discarded) {
109 ASTScope scope(this, is_discarded);
110 ConsumeToken(OfKind(Token::Kind::kIdentifier));
111 if (!Ok())
112 return Fail();
113
114 return std::make_unique<raw::Identifier>(scope.GetSourceElement());
115 }
116
ParseCompoundIdentifier()117 std::unique_ptr<raw::CompoundIdentifier> Parser::ParseCompoundIdentifier() {
118 ASTScope scope(this);
119 std::vector<std::unique_ptr<raw::Identifier>> components;
120
121 components.emplace_back(ParseIdentifier());
122 if (!Ok())
123 return Fail();
124
125 auto parse_component = [&components, this]() {
126 switch (Peek().combined()) {
127 default:
128 return Done;
129
130 case CASE_TOKEN(Token::Kind::kDot):
131 ConsumeToken(OfKind(Token::Kind::kDot));
132 if (Ok()) {
133 components.emplace_back(ParseIdentifier());
134 }
135 return More;
136 }
137 };
138
139 while (parse_component() == More) {
140 if (!Ok())
141 return Fail();
142 }
143
144 return std::make_unique<raw::CompoundIdentifier>(scope.GetSourceElement(), std::move(components));
145 }
146
ParseStringLiteral()147 std::unique_ptr<raw::StringLiteral> Parser::ParseStringLiteral() {
148 ASTScope scope(this);
149 ConsumeToken(OfKind(Token::Kind::kStringLiteral));
150 if (!Ok())
151 return Fail();
152
153 return std::make_unique<raw::StringLiteral>(scope.GetSourceElement());
154 }
155
ParseNumericLiteral()156 std::unique_ptr<raw::NumericLiteral> Parser::ParseNumericLiteral() {
157 ASTScope scope(this);
158 ConsumeToken(OfKind(Token::Kind::kNumericLiteral));
159 if (!Ok())
160 return Fail();
161
162 return std::make_unique<raw::NumericLiteral>(scope.GetSourceElement());
163 }
164
ParseTrueLiteral()165 std::unique_ptr<raw::TrueLiteral> Parser::ParseTrueLiteral() {
166 ASTScope scope(this);
167 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kTrue));
168 if (!Ok())
169 return Fail();
170
171 return std::make_unique<raw::TrueLiteral>(scope.GetSourceElement());
172 }
173
ParseFalseLiteral()174 std::unique_ptr<raw::FalseLiteral> Parser::ParseFalseLiteral() {
175 ASTScope scope(this);
176 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kFalse));
177 if (!Ok())
178 return Fail();
179
180 return std::make_unique<raw::FalseLiteral>(scope.GetSourceElement());
181 }
182
ParseLiteral()183 std::unique_ptr<raw::Literal> Parser::ParseLiteral() {
184 switch (Peek().combined()) {
185 case CASE_TOKEN(Token::Kind::kStringLiteral):
186 return ParseStringLiteral();
187
188 case CASE_TOKEN(Token::Kind::kNumericLiteral):
189 return ParseNumericLiteral();
190
191 case CASE_IDENTIFIER(Token::Subkind::kTrue):
192 return ParseTrueLiteral();
193
194 case CASE_IDENTIFIER(Token::Subkind::kFalse):
195 return ParseFalseLiteral();
196
197 default:
198 return Fail();
199 }
200 }
201
ParseAttribute()202 std::unique_ptr<raw::Attribute> Parser::ParseAttribute() {
203 ASTScope scope(this);
204 auto name = ParseIdentifier();
205 if (!Ok())
206 return Fail();
207 std::unique_ptr<raw::StringLiteral> value;
208 if (MaybeConsumeToken(OfKind(Token::Kind::kEqual))) {
209 value = ParseStringLiteral();
210 if (!Ok())
211 return Fail();
212 }
213
214 std::string str_name("");
215 std::string str_value("");
216 if (name)
217 str_name = std::string(name->location().data().data(), name->location().data().size());
218 if (value) {
219 auto data = value->location().data();
220 if (data.size() >= 2 && data[0] == '"' && data[data.size() - 1] == '"') {
221 str_value = std::string(value->location().data().data() + 1, value->location().data().size() - 2);
222 }
223 }
224 return std::make_unique<raw::Attribute>(scope.GetSourceElement(), str_name, str_value);
225 }
226
ParseAttributeList(std::unique_ptr<raw::Attribute> && doc_comment,ASTScope & scope)227 std::unique_ptr<raw::AttributeList> Parser::ParseAttributeList(std::unique_ptr<raw::Attribute>&& doc_comment, ASTScope& scope) {
228 auto attributes = std::make_unique<raw::Attributes>();
229 if (doc_comment) {
230 attributes->Insert(std::move(doc_comment));
231 }
232 ConsumeToken(OfKind(Token::Kind::kLeftSquare));
233 if (!Ok())
234 return Fail();
235 for (;;) {
236 auto attribute = ParseAttribute();
237 if (!Ok())
238 return Fail();
239 auto attribute_name = attribute->name;
240 if (!attributes->Insert(std::move(attribute))) {
241 std::string message("Duplicate attribute with name '");
242 message += attribute_name;
243 message += "'";
244 return Fail(message);
245 }
246 if (!MaybeConsumeToken(OfKind(Token::Kind::kComma)))
247 break;
248 }
249 ConsumeToken(OfKind(Token::Kind::kRightSquare));
250 if (!Ok())
251 return Fail();
252 auto attribute_list = std::make_unique<raw::AttributeList>(scope.GetSourceElement(), std::move(attributes));
253 return attribute_list;
254 }
255
ParseDocComment()256 std::unique_ptr<raw::Attribute> Parser::ParseDocComment() {
257 ASTScope scope(this);
258 std::string str_value("");
259
260 Token doc_line;
261 while (Peek().kind() == Token::Kind::kDocComment) {
262 doc_line = ConsumeToken(OfKind(Token::Kind::kDocComment));
263 str_value += std::string(doc_line.location().data().data() + 3, doc_line.location().data().size() - 2);
264 assert(Ok());
265 }
266 return std::make_unique<raw::Attribute>(scope.GetSourceElement(), "Doc", std::move(str_value));
267 }
268
MaybeParseAttributeList()269 std::unique_ptr<raw::AttributeList> Parser::MaybeParseAttributeList() {
270 ASTScope scope(this);
271 std::unique_ptr<raw::Attribute> doc_comment;
272 // Doc comments must appear above attributes
273 if (Peek().kind() == Token::Kind::kDocComment) {
274 doc_comment = ParseDocComment();
275 }
276 if (Peek().kind() == Token::Kind::kLeftSquare) {
277 return ParseAttributeList(std::move(doc_comment), scope);
278 }
279 // no generic attributes, start the attribute list
280 if (doc_comment) {
281 auto attributes = std::make_unique<raw::Attributes>();
282 attributes->Insert(std::move(doc_comment));
283 return std::make_unique<raw::AttributeList>(scope.GetSourceElement(), std::move(attributes));
284 }
285 return nullptr;
286 }
287
ParseConstant()288 std::unique_ptr<raw::Constant> Parser::ParseConstant() {
289 switch (Peek().combined()) {
290 case CASE_TOKEN(Token::Kind::kIdentifier): {
291 auto identifier = ParseCompoundIdentifier();
292 if (!Ok())
293 return Fail();
294 return std::make_unique<raw::IdentifierConstant>(std::move(identifier));
295 }
296
297 TOKEN_LITERAL_CASES : {
298 auto literal = ParseLiteral();
299 if (!Ok())
300 return Fail();
301 return std::make_unique<raw::LiteralConstant>(std::move(literal));
302 }
303
304 default:
305 return Fail();
306 }
307 }
308
ParseUsing()309 std::unique_ptr<raw::Using> Parser::ParseUsing() {
310 ASTScope scope(this);
311 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kUsing));
312 if (!Ok())
313 return Fail();
314 auto using_path = ParseCompoundIdentifier();
315 if (!Ok())
316 return Fail();
317
318 std::unique_ptr<raw::Identifier> maybe_alias;
319 std::unique_ptr<raw::PrimitiveType> maybe_primitive;
320
321 if (MaybeConsumeToken(IdentifierOfSubkind(Token::Subkind::kAs))) {
322 if (!Ok())
323 return Fail();
324 maybe_alias = ParseIdentifier();
325 if (!Ok())
326 return Fail();
327 } else if (MaybeConsumeToken(OfKind(Token::Kind::kEqual))) {
328 if (!Ok() || using_path->components.size() != 1u)
329 return Fail();
330 maybe_primitive = ParsePrimitiveType();
331 if (!Ok())
332 return Fail();
333 }
334
335 return std::make_unique<raw::Using>(scope.GetSourceElement(), std::move(using_path), std::move(maybe_alias), std::move(maybe_primitive));
336 }
337
ParseArrayType()338 std::unique_ptr<raw::ArrayType> Parser::ParseArrayType() {
339 ASTScope scope(this);
340 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kArray));
341 if (!Ok())
342 return Fail();
343 ConsumeToken(OfKind(Token::Kind::kLeftAngle));
344 if (!Ok())
345 return Fail();
346 auto element_type = ParseType();
347 if (!Ok())
348 return Fail();
349 ConsumeToken(OfKind(Token::Kind::kRightAngle));
350 if (!Ok())
351 return Fail();
352 ConsumeToken(OfKind(Token::Kind::kColon));
353 if (!Ok())
354 return Fail();
355 auto element_count = ParseConstant();
356 if (!Ok())
357 return Fail();
358
359 return std::make_unique<raw::ArrayType>(scope.GetSourceElement(), std::move(element_type), std::move(element_count));
360 }
361
ParseVectorType()362 std::unique_ptr<raw::VectorType> Parser::ParseVectorType() {
363 ASTScope scope(this);
364 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kVector));
365 if (!Ok())
366 return Fail();
367 ConsumeToken(OfKind(Token::Kind::kLeftAngle));
368 if (!Ok())
369 return Fail();
370 auto element_type = ParseType();
371 if (!Ok())
372 return Fail();
373 ConsumeToken(OfKind(Token::Kind::kRightAngle));
374 if (!Ok())
375 return Fail();
376
377 std::unique_ptr<raw::Constant> maybe_element_count;
378 if (MaybeConsumeToken(OfKind(Token::Kind::kColon))) {
379 if (!Ok())
380 return Fail();
381 maybe_element_count = ParseConstant();
382 if (!Ok())
383 return Fail();
384 }
385
386 auto nullability = types::Nullability::kNonnullable;
387 if (MaybeConsumeToken(OfKind(Token::Kind::kQuestion))) {
388 nullability = types::Nullability::kNullable;
389 }
390
391 return std::make_unique<raw::VectorType>(scope.GetSourceElement(), std::move(element_type),
392 std::move(maybe_element_count), nullability);
393 }
394
ParseStringType()395 std::unique_ptr<raw::StringType> Parser::ParseStringType() {
396 ASTScope scope(this);
397 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kString));
398 if (!Ok())
399 return Fail();
400
401 std::unique_ptr<raw::Constant> maybe_element_count;
402 if (MaybeConsumeToken(OfKind(Token::Kind::kColon))) {
403 if (!Ok())
404 return Fail();
405 maybe_element_count = ParseConstant();
406 if (!Ok())
407 return Fail();
408 }
409
410 auto nullability = types::Nullability::kNonnullable;
411 if (MaybeConsumeToken(OfKind(Token::Kind::kQuestion))) {
412 nullability = types::Nullability::kNullable;
413 }
414
415 return std::make_unique<raw::StringType>(scope.GetSourceElement(), std::move(maybe_element_count), nullability);
416 }
417
ParseHandleType()418 std::unique_ptr<raw::HandleType> Parser::ParseHandleType() {
419 ASTScope scope(this);
420 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kHandle));
421 if (!Ok())
422 return Fail();
423
424 auto subtype = types::HandleSubtype::kHandle;
425 if (MaybeConsumeToken(OfKind(Token::Kind::kLeftAngle))) {
426 if (!Ok())
427 return Fail();
428 auto identifier = ParseIdentifier(true);
429 if (!Ok())
430 return Fail();
431 if (!LookupHandleSubtype(identifier.get(), &subtype))
432 return Fail();
433 ConsumeToken(OfKind(Token::Kind::kRightAngle));
434 if (!Ok())
435 return Fail();
436 }
437
438 auto nullability = types::Nullability::kNonnullable;
439 if (MaybeConsumeToken(OfKind(Token::Kind::kQuestion))) {
440 nullability = types::Nullability::kNullable;
441 }
442
443 return std::make_unique<raw::HandleType>(scope.GetSourceElement(), subtype, nullability);
444 }
445
ParsePrimitiveType()446 std::unique_ptr<raw::PrimitiveType> Parser::ParsePrimitiveType() {
447 types::PrimitiveSubtype subtype;
448
449 switch (Peek().combined()) {
450 case CASE_IDENTIFIER(Token::Subkind::kBool):
451 subtype = types::PrimitiveSubtype::kBool;
452 break;
453 case CASE_IDENTIFIER(Token::Subkind::kInt8):
454 subtype = types::PrimitiveSubtype::kInt8;
455 break;
456 case CASE_IDENTIFIER(Token::Subkind::kInt16):
457 subtype = types::PrimitiveSubtype::kInt16;
458 break;
459 case CASE_IDENTIFIER(Token::Subkind::kInt32):
460 subtype = types::PrimitiveSubtype::kInt32;
461 break;
462 case CASE_IDENTIFIER(Token::Subkind::kInt64):
463 subtype = types::PrimitiveSubtype::kInt64;
464 break;
465 case CASE_IDENTIFIER(Token::Subkind::kUint8):
466 subtype = types::PrimitiveSubtype::kUint8;
467 break;
468 case CASE_IDENTIFIER(Token::Subkind::kUint16):
469 subtype = types::PrimitiveSubtype::kUint16;
470 break;
471 case CASE_IDENTIFIER(Token::Subkind::kUint32):
472 subtype = types::PrimitiveSubtype::kUint32;
473 break;
474 case CASE_IDENTIFIER(Token::Subkind::kUint64):
475 subtype = types::PrimitiveSubtype::kUint64;
476 break;
477 case CASE_IDENTIFIER(Token::Subkind::kFloat32):
478 subtype = types::PrimitiveSubtype::kFloat32;
479 break;
480 case CASE_IDENTIFIER(Token::Subkind::kFloat64):
481 subtype = types::PrimitiveSubtype::kFloat64;
482 break;
483 case CASE_IDENTIFIER(Token::Subkind::kUSize):
484 subtype = types::PrimitiveSubtype::kUSize;
485 break;
486 case CASE_IDENTIFIER(Token::Subkind::kISize):
487 subtype = types::PrimitiveSubtype::kISize;
488 break;
489 case CASE_IDENTIFIER(Token::Subkind::kVoidPtr):
490 subtype = types::PrimitiveSubtype::kVoidPtr;
491 break;
492 default:
493 return Fail();
494 }
495 ASTScope scope(this);
496 ConsumeToken(OfKind(Peek().kind()));
497 if (!Ok())
498 return Fail();
499 return std::make_unique<raw::PrimitiveType>(scope.GetSourceElement(), subtype);
500 }
501
ParseRequestHandleType()502 std::unique_ptr<raw::RequestHandleType> Parser::ParseRequestHandleType() {
503 ASTScope scope(this);
504 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kRequest));
505 if (!Ok())
506 return Fail();
507 ConsumeToken(OfKind(Token::Kind::kLeftAngle));
508 if (!Ok())
509 return Fail();
510 auto identifier = ParseCompoundIdentifier();
511 if (!Ok())
512 return Fail();
513 ConsumeToken(OfKind(Token::Kind::kRightAngle));
514 if (!Ok())
515 return Fail();
516
517 auto nullability = types::Nullability::kNonnullable;
518 if (MaybeConsumeToken(OfKind(Token::Kind::kQuestion))) {
519 nullability = types::Nullability::kNullable;
520 }
521
522 return std::make_unique<raw::RequestHandleType>(scope.GetSourceElement(), std::move(identifier), nullability);
523 }
524
ParseType()525 std::unique_ptr<raw::Type> Parser::ParseType() {
526 switch (Peek().combined()) {
527 case CASE_TOKEN(Token::Kind::kIdentifier): {
528 ASTScope scope(this);
529 auto identifier = ParseCompoundIdentifier();
530 if (!Ok())
531 return Fail();
532 auto nullability = types::Nullability::kNonnullable;
533 if (MaybeConsumeToken(OfKind(Token::Kind::kQuestion))) {
534 if (!Ok())
535 return Fail();
536 nullability = types::Nullability::kNullable;
537 }
538 return std::make_unique<raw::IdentifierType>(scope.GetSourceElement(), std::move(identifier), nullability);
539 }
540
541 case CASE_IDENTIFIER(Token::Subkind::kArray): {
542 auto type = ParseArrayType();
543 if (!Ok())
544 return Fail();
545 return type;
546 }
547
548 case CASE_IDENTIFIER(Token::Subkind::kVector): {
549 auto type = ParseVectorType();
550 if (!Ok())
551 return Fail();
552 return type;
553 }
554
555 case CASE_IDENTIFIER(Token::Subkind::kString): {
556 auto type = ParseStringType();
557 if (!Ok())
558 return Fail();
559 return type;
560 }
561
562 case CASE_IDENTIFIER(Token::Subkind::kHandle): {
563 auto type = ParseHandleType();
564 if (!Ok())
565 return Fail();
566 return type;
567 }
568
569 case CASE_IDENTIFIER(Token::Subkind::kRequest): {
570 auto type = ParseRequestHandleType();
571 if (!Ok())
572 return Fail();
573 return type;
574 }
575
576 TOKEN_PRIMITIVE_TYPE_CASES : {
577 auto type = ParsePrimitiveType();
578 if (!Ok())
579 return Fail();
580 return type;
581 }
582
583 default:
584 return Fail();
585 }
586 }
587
588 std::unique_ptr<raw::ConstDeclaration>
ParseConstDeclaration(std::unique_ptr<raw::AttributeList> attributes,ASTScope & scope)589 Parser::ParseConstDeclaration(std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope) {
590 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kConst));
591
592 if (!Ok())
593 return Fail();
594 auto type = ParseType();
595 if (!Ok())
596 return Fail();
597 auto identifier = ParseIdentifier();
598 if (!Ok())
599 return Fail();
600 ConsumeToken(OfKind(Token::Kind::kEqual));
601 if (!Ok())
602 return Fail();
603 auto constant = ParseConstant();
604 if (!Ok())
605 return Fail();
606
607 return std::make_unique<raw::ConstDeclaration>(scope.GetSourceElement(), std::move(attributes), std::move(type),
608 std::move(identifier), std::move(constant));
609 }
610
ParseEnumMember()611 std::unique_ptr<raw::EnumMember> Parser::ParseEnumMember() {
612 ASTScope scope(this);
613 auto attributes = MaybeParseAttributeList();
614 if (!Ok())
615 return Fail();
616 auto identifier = ParseIdentifier();
617 if (!Ok())
618 return Fail();
619
620 ConsumeToken(OfKind(Token::Kind::kEqual));
621 if (!Ok())
622 return Fail();
623
624 auto member_value = ParseConstant();
625 if (!Ok())
626 return Fail();
627
628 return std::make_unique<raw::EnumMember>(scope.GetSourceElement(), std::move(identifier), std::move(member_value), std::move(attributes));
629 }
630
631 std::unique_ptr<raw::EnumDeclaration>
ParseEnumDeclaration(std::unique_ptr<raw::AttributeList> attributes,ASTScope & scope)632 Parser::ParseEnumDeclaration(std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope) {
633 std::vector<std::unique_ptr<raw::EnumMember>> members;
634 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kEnum));
635
636 if (!Ok())
637 return Fail();
638 auto identifier = ParseIdentifier();
639 if (!Ok())
640 return Fail();
641 std::unique_ptr<raw::PrimitiveType> subtype;
642 if (MaybeConsumeToken(OfKind(Token::Kind::kColon))) {
643 if (!Ok())
644 return Fail();
645 subtype = ParsePrimitiveType();
646 if (!Ok())
647 return Fail();
648 }
649 ConsumeToken(OfKind(Token::Kind::kLeftCurly));
650 if (!Ok())
651 return Fail();
652
653 auto parse_member = [&members, this]() {
654 switch (Peek().combined()) {
655 default:
656 ConsumeToken(OfKind(Token::Kind::kRightCurly));
657 return Done;
658
659 TOKEN_ATTR_CASES:
660 // intentional fallthrough for attribute parsing
661 TOKEN_TYPE_CASES:
662 members.emplace_back(ParseEnumMember());
663 return More;
664 }
665 };
666
667 while (parse_member() == More) {
668 if (!Ok())
669 Fail();
670 ConsumeToken(OfKind(Token::Kind::kSemicolon));
671 if (!Ok())
672 return Fail();
673 }
674 if (!Ok())
675 Fail();
676
677 // TODO(surajmalhotra): REMOVE THIS HACK.
678 #if 0
679 if (members.empty())
680 return Fail();
681 #endif
682
683 return std::make_unique<raw::EnumDeclaration>(scope.GetSourceElement(),
684 std::move(attributes), std::move(identifier),
685 std::move(subtype), std::move(members));
686 }
687
ParseParameter()688 std::unique_ptr<raw::Parameter> Parser::ParseParameter() {
689 ASTScope scope(this);
690 auto type = ParseType();
691 if (!Ok())
692 return Fail();
693 auto identifier = ParseIdentifier();
694 if (!Ok())
695 return Fail();
696
697 return std::make_unique<raw::Parameter>(scope.GetSourceElement(), std::move(type), std::move(identifier));
698 }
699
ParseParameterList()700 std::unique_ptr<raw::ParameterList> Parser::ParseParameterList() {
701 ASTScope scope(this);
702 std::vector<std::unique_ptr<raw::Parameter>> parameter_list;
703
704 switch (Peek().combined()) {
705 default:
706 break;
707
708 TOKEN_TYPE_CASES:
709 auto parameter = ParseParameter();
710 parameter_list.emplace_back(std::move(parameter));
711 if (!Ok())
712 return Fail();
713 while (Peek().kind() == Token::Kind::kComma) {
714 ConsumeToken(OfKind(Token::Kind::kComma));
715 if (!Ok())
716 return Fail();
717 switch (Peek().combined()) {
718 TOKEN_TYPE_CASES:
719 parameter_list.emplace_back(ParseParameter());
720 if (!Ok())
721 return Fail();
722 break;
723
724 default:
725 return Fail();
726 }
727 }
728 }
729
730 return std::make_unique<raw::ParameterList>(scope.GetSourceElement(), std::move(parameter_list));
731 }
732
ParseInterfaceMethod(std::unique_ptr<raw::AttributeList> attributes,ASTScope & scope)733 std::unique_ptr<raw::InterfaceMethod> Parser::ParseInterfaceMethod(std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope) {
734 std::unique_ptr<raw::Identifier> method_name;
735 std::unique_ptr<raw::ParameterList> maybe_request;
736 std::unique_ptr<raw::ParameterList> maybe_response;
737
738 auto parse_params = [this](std::unique_ptr<raw::ParameterList>* params_out) {
739 ConsumeToken(OfKind(Token::Kind::kLeftParen));
740 if (!Ok())
741 return false;
742 *params_out = ParseParameterList();
743 if (!Ok())
744 return false;
745 ConsumeToken(OfKind(Token::Kind::kRightParen));
746 if (!Ok())
747 return false;
748 return true;
749 };
750
751 if (MaybeConsumeToken(OfKind(Token::Kind::kArrow))) {
752 method_name = ParseIdentifier();
753 if (!Ok())
754 return Fail();
755 if (!parse_params(&maybe_response))
756 return Fail();
757 } else {
758 method_name = ParseIdentifier();
759 if (!Ok())
760 return Fail();
761 if (!parse_params(&maybe_request))
762 return Fail();
763
764 if (MaybeConsumeToken(OfKind(Token::Kind::kArrow))) {
765 if (!Ok())
766 return Fail();
767 if (!parse_params(&maybe_response))
768 return Fail();
769 }
770 }
771
772 assert(method_name);
773 assert(maybe_request || maybe_response);
774
775 return std::make_unique<raw::InterfaceMethod>(scope.GetSourceElement(),
776 std::move(attributes),
777 std::move(method_name),
778 std::move(maybe_request),
779 std::move(maybe_response));
780 }
781
782 std::unique_ptr<raw::InterfaceDeclaration>
ParseInterfaceDeclaration(std::unique_ptr<raw::AttributeList> attributes,ASTScope & scope)783 Parser::ParseInterfaceDeclaration(std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope) {
784 std::vector<std::unique_ptr<raw::CompoundIdentifier>> superinterfaces;
785 std::vector<std::unique_ptr<raw::InterfaceMethod>> methods;
786
787 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kInterface));
788
789 if (!Ok())
790 return Fail();
791
792 auto identifier = ParseIdentifier();
793 if (!Ok())
794 return Fail();
795
796 if (MaybeConsumeToken(OfKind(Token::Kind::kColon))) {
797 for (;;) {
798 superinterfaces.emplace_back(ParseCompoundIdentifier());
799 if (!Ok())
800 return Fail();
801 if (!MaybeConsumeToken(OfKind(Token::Kind::kComma)))
802 break;
803 }
804 }
805
806 ConsumeToken(OfKind(Token::Kind::kLeftCurly));
807 if (!Ok())
808 return Fail();
809
810 auto parse_member = [&methods, this]() {
811 ASTScope scope(this);
812 std::unique_ptr<raw::AttributeList> attributes = MaybeParseAttributeList();
813 if (!Ok())
814 return More;
815
816 switch (Peek().kind()) {
817 default:
818 ConsumeToken(OfKind(Token::Kind::kRightCurly));
819 return Done;
820
821 case Token::Kind::kArrow:
822 case Token::Kind::kIdentifier:
823 methods.emplace_back(ParseInterfaceMethod(std::move(attributes), scope));
824 return More;
825 }
826 };
827
828 while (parse_member() == More) {
829 if (!Ok())
830 Fail();
831 ConsumeToken(OfKind(Token::Kind::kSemicolon));
832 if (!Ok())
833 return Fail();
834 }
835 if (!Ok())
836 Fail();
837
838 return std::make_unique<raw::InterfaceDeclaration>(scope.GetSourceElement(),
839 std::move(attributes), std::move(identifier),
840 std::move(superinterfaces),
841 std::move(methods));
842 }
843
ParseStructMember()844 std::unique_ptr<raw::StructMember> Parser::ParseStructMember() {
845 ASTScope scope(this);
846 auto attributes = MaybeParseAttributeList();
847 if (!Ok())
848 return Fail();
849 auto type = ParseType();
850 if (!Ok())
851 return Fail();
852 auto identifier = ParseIdentifier();
853 if (!Ok())
854 return Fail();
855
856 std::unique_ptr<raw::Constant> maybe_default_value;
857 if (MaybeConsumeToken(OfKind(Token::Kind::kEqual))) {
858 if (!Ok())
859 return Fail();
860 maybe_default_value = ParseConstant();
861 if (!Ok())
862 return Fail();
863 }
864
865 return std::make_unique<raw::StructMember>(scope.GetSourceElement(),
866 std::move(type), std::move(identifier),
867 std::move(maybe_default_value), std::move(attributes));
868 }
869
870 std::unique_ptr<raw::StructDeclaration>
ParseStructDeclaration(std::unique_ptr<raw::AttributeList> attributes,ASTScope & scope)871 Parser::ParseStructDeclaration(std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope) {
872 std::vector<std::unique_ptr<raw::StructMember>> members;
873
874 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kStruct));
875 if (!Ok())
876 return Fail();
877 auto identifier = ParseIdentifier();
878 if (!Ok())
879 return Fail();
880 ConsumeToken(OfKind(Token::Kind::kLeftCurly));
881 if (!Ok())
882 return Fail();
883
884 auto parse_member = [&members, this]() {
885 switch (Peek().combined()) {
886 default:
887 ConsumeToken(OfKind(Token::Kind::kRightCurly));
888 return Done;
889
890 TOKEN_ATTR_CASES:
891 // intentional fallthrough for attribute parsing
892 TOKEN_TYPE_CASES:
893 members.emplace_back(ParseStructMember());
894 return More;
895 }
896 };
897
898 while (parse_member() == More) {
899 if (!Ok())
900 Fail();
901 ConsumeToken(OfKind(Token::Kind::kSemicolon));
902 if (!Ok())
903 return Fail();
904 }
905 if (!Ok())
906 Fail();
907
908 // TODO(surajmalhotra): REMOVE THIS HACK.
909 #if 0
910 if (members.empty())
911 return Fail();
912 #endif
913
914 return std::make_unique<raw::StructDeclaration>(scope.GetSourceElement(),
915 std::move(attributes), std::move(identifier),
916 std::move(members));
917 }
918
ParseUnionMember()919 std::unique_ptr<raw::UnionMember> Parser::ParseUnionMember() {
920 ASTScope scope(this);
921 auto attributes = MaybeParseAttributeList();
922 if (!Ok())
923 return Fail();
924 auto type = ParseType();
925 if (!Ok())
926 return Fail();
927 auto identifier = ParseIdentifier();
928 if (!Ok())
929 return Fail();
930
931 return std::make_unique<raw::UnionMember>(scope.GetSourceElement(), std::move(type), std::move(identifier), std::move(attributes));
932 }
933
934 std::unique_ptr<raw::UnionDeclaration>
ParseUnionDeclaration(std::unique_ptr<raw::AttributeList> attributes,ASTScope & scope)935 Parser::ParseUnionDeclaration(std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope) {
936 std::vector<std::unique_ptr<raw::UnionMember>> members;
937
938 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kUnion));
939 if (!Ok())
940 return Fail();
941 auto identifier = ParseIdentifier();
942 if (!Ok())
943 return Fail();
944 ConsumeToken(OfKind(Token::Kind::kLeftCurly));
945 if (!Ok())
946 return Fail();
947
948 auto parse_member = [&members, this]() {
949 switch (Peek().combined()) {
950 default:
951 ConsumeToken(OfKind(Token::Kind::kRightCurly));
952 return Done;
953
954 TOKEN_ATTR_CASES:
955 // intentional fallthrough for attribute parsing
956 TOKEN_TYPE_CASES:
957 members.emplace_back(ParseUnionMember());
958 return More;
959 }
960 };
961
962 while (parse_member() == More) {
963 if (!Ok())
964 Fail();
965 ConsumeToken(OfKind(Token::Kind::kSemicolon));
966 if (!Ok())
967 return Fail();
968 }
969 if (!Ok())
970 Fail();
971
972 if (members.empty())
973 Fail();
974
975 return std::make_unique<raw::UnionDeclaration>(scope.GetSourceElement(),
976 std::move(attributes), std::move(identifier),
977 std::move(members));
978 }
979
ParseFile()980 std::unique_ptr<raw::File> Parser::ParseFile() {
981 ASTScope scope(this);
982 std::vector<std::unique_ptr<raw::Using>> using_list;
983 std::vector<std::unique_ptr<raw::ConstDeclaration>> const_declaration_list;
984 std::vector<std::unique_ptr<raw::EnumDeclaration>> enum_declaration_list;
985 std::vector<std::unique_ptr<raw::InterfaceDeclaration>> interface_declaration_list;
986 std::vector<std::unique_ptr<raw::StructDeclaration>> struct_declaration_list;
987 std::vector<std::unique_ptr<raw::UnionDeclaration>> union_declaration_list;
988
989 auto attributes = MaybeParseAttributeList();
990 if (!Ok())
991 return Fail();
992 ConsumeToken(IdentifierOfSubkind(Token::Subkind::kLibrary));
993 if (!Ok())
994 return Fail();
995 auto library_name = ParseCompoundIdentifier();
996 if (!Ok())
997 return Fail();
998 ConsumeToken(OfKind(Token::Kind::kSemicolon));
999 if (!Ok())
1000 return Fail();
1001
1002 auto parse_using = [&using_list, this]() {
1003 switch (Peek().combined()) {
1004 default:
1005 return Done;
1006
1007 case CASE_IDENTIFIER(Token::Subkind::kUsing):
1008 using_list.emplace_back(ParseUsing());
1009 return More;
1010 }
1011 };
1012
1013 while (parse_using() == More) {
1014 if (!Ok())
1015 return Fail();
1016 ConsumeToken(OfKind(Token::Kind::kSemicolon));
1017 if (!Ok())
1018 return Fail();
1019 }
1020
1021 auto parse_declaration = [&const_declaration_list, &enum_declaration_list,
1022 &interface_declaration_list, &struct_declaration_list,
1023 &union_declaration_list, this]() {
1024 ASTScope scope(this);
1025 std::unique_ptr<raw::AttributeList> attributes = MaybeParseAttributeList();
1026 if (!Ok())
1027 return More;
1028
1029 switch (Peek().combined()) {
1030 default:
1031 return Done;
1032
1033 case CASE_IDENTIFIER(Token::Subkind::kConst):
1034 const_declaration_list.emplace_back(ParseConstDeclaration(std::move(attributes), scope));
1035 return More;
1036
1037 case CASE_IDENTIFIER(Token::Subkind::kEnum):
1038 enum_declaration_list.emplace_back(ParseEnumDeclaration(std::move(attributes), scope));
1039 return More;
1040
1041 case CASE_IDENTIFIER(Token::Subkind::kInterface):
1042 interface_declaration_list.emplace_back(
1043 ParseInterfaceDeclaration(std::move(attributes), scope));
1044 return More;
1045
1046 case CASE_IDENTIFIER(Token::Subkind::kStruct):
1047 struct_declaration_list.emplace_back(ParseStructDeclaration(std::move(attributes), scope));
1048 return More;
1049
1050 case CASE_IDENTIFIER(Token::Subkind::kUnion):
1051 union_declaration_list.emplace_back(ParseUnionDeclaration(std::move(attributes), scope));
1052 return More;
1053 }
1054 };
1055
1056 while (parse_declaration() == More) {
1057 if (!Ok())
1058 return Fail();
1059 ConsumeToken(OfKind(Token::Kind::kSemicolon));
1060 if (!Ok())
1061 return Fail();
1062 }
1063
1064 Token end = ConsumeToken(OfKind(Token::Kind::kEndOfFile));
1065 if (!Ok())
1066 return Fail();
1067
1068 return std::make_unique<raw::File>(
1069 scope.GetSourceElement(), end,
1070 std::move(attributes), std::move(library_name), std::move(using_list), std::move(const_declaration_list),
1071 std::move(enum_declaration_list), std::move(interface_declaration_list),
1072 std::move(struct_declaration_list), std::move(union_declaration_list));
1073 }
1074
1075 } // namespace banjo
1076