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