Serenity Operating System
1/*
2 * Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include "Parser.h"
8#include "AST.h"
9#include <AK/Debug.h>
10#include <AK/ScopeGuard.h>
11#include <AK/ScopeLogger.h>
12#include <LibCpp/Lexer.h>
13
14#define LOG_SCOPE() ScopeLogger<CPP_DEBUG> logger(DeprecatedString::formatted("'{}' - {} ({})", peek().text(), peek().type_as_deprecated_string(), m_state.token_index))
15
16namespace Cpp {
17
18Parser::Parser(Vector<Token> tokens, DeprecatedString const& filename)
19 : m_filename(filename)
20 , m_tokens(move(tokens))
21{
22 if constexpr (CPP_DEBUG) {
23 dbgln("Tokens:");
24 for (size_t i = 0; i < m_tokens.size(); ++i) {
25 dbgln("{}- {}", i, m_tokens[i].to_deprecated_string());
26 }
27 }
28}
29
30NonnullRefPtr<TranslationUnit> Parser::parse()
31{
32 LOG_SCOPE();
33 if (m_tokens.is_empty())
34 return create_root_ast_node({}, {});
35 auto unit = create_root_ast_node(m_tokens.first().start(), m_tokens.last().end());
36 unit->set_declarations(parse_declarations_in_translation_unit(*unit));
37 return unit;
38}
39
40Vector<NonnullRefPtr<Declaration const>> Parser::parse_declarations_in_translation_unit(ASTNode const& parent)
41{
42 Vector<NonnullRefPtr<Declaration const>> declarations;
43 while (!eof()) {
44 auto declaration = parse_single_declaration_in_translation_unit(parent);
45 if (declaration) {
46 declarations.append(declaration.release_nonnull());
47 } else {
48 error("unexpected token"sv);
49 consume();
50 }
51 }
52 return declarations;
53}
54
55RefPtr<Declaration const> Parser::parse_single_declaration_in_translation_unit(ASTNode const& parent)
56{
57 while (!eof()) {
58 if (match_comment()) {
59 consume(Token::Type::Comment);
60 continue;
61 }
62
63 if (match_preprocessor()) {
64 consume_preprocessor();
65 continue;
66 }
67
68 auto declaration = match_declaration_in_translation_unit();
69 if (declaration.has_value()) {
70 return parse_declaration(parent, declaration.value());
71 }
72 return {};
73 }
74 return {};
75}
76
77NonnullRefPtr<Declaration const> Parser::parse_declaration(ASTNode const& parent, DeclarationType declaration_type)
78{
79 switch (declaration_type) {
80 case DeclarationType::Function:
81 return parse_function_declaration(parent);
82 case DeclarationType::Variable:
83 return parse_variable_declaration(parent);
84 case DeclarationType::Enum:
85 return parse_enum_declaration(parent);
86 case DeclarationType::Class:
87 return parse_class_declaration(parent);
88 case DeclarationType::Namespace:
89 return parse_namespace_declaration(parent);
90 case DeclarationType::Constructor:
91 return parse_constructor(parent);
92 case DeclarationType::Destructor:
93 return parse_destructor(parent);
94 case DeclarationType::UsingNamespace:
95 return parse_using_namespace_declaration(parent);
96 default:
97 error("unexpected declaration type"sv);
98 return create_ast_node<InvalidDeclaration>(parent, position(), position());
99 }
100}
101
102NonnullRefPtr<FunctionDeclaration const> Parser::parse_function_declaration(ASTNode const& parent)
103{
104 auto func = create_ast_node<FunctionDeclaration>(parent, position(), {});
105
106 func->set_qualifiers(parse_function_qualifiers());
107 func->set_return_type(parse_type(*func));
108
109 func->set_name(parse_name(*func));
110
111 consume(Token::Type::LeftParen);
112 auto parameters = parse_parameter_list(*func);
113 if (parameters.has_value())
114 func->set_parameters(parameters.value());
115
116 consume(Token::Type::RightParen);
117
118 while (match_keyword("const") || match_keyword("override")) {
119 consume();
120 // FIXME: Note that this function is supposed to be a class member, and `this` has to be const, somehow.
121 }
122
123 RefPtr<FunctionDefinition const> body;
124 Position func_end {};
125 if (peek(Token::Type::LeftCurly).has_value()) {
126 body = parse_function_definition(*func);
127 func_end = body->end();
128 } else {
129 func_end = position();
130 if (match_attribute_specification())
131 consume_attribute_specification(); // we don't use the value of __attribute__
132 consume(Token::Type::Semicolon);
133 }
134
135 func->set_definition(move(body));
136 func->set_end(func_end);
137 return func;
138}
139
140NonnullRefPtr<FunctionDefinition const> Parser::parse_function_definition(ASTNode const& parent)
141{
142 LOG_SCOPE();
143 auto func = create_ast_node<FunctionDefinition>(parent, position(), {});
144 consume(Token::Type::LeftCurly);
145 while (!eof() && peek().type() != Token::Type::RightCurly) {
146 func->add_statement(parse_statement(func));
147 }
148 func->set_end(position());
149 if (!eof())
150 consume(Token::Type::RightCurly);
151 return func;
152}
153
154NonnullRefPtr<Statement const> Parser::parse_statement(ASTNode const& parent)
155{
156 LOG_SCOPE();
157 ArmedScopeGuard consume_semicolon([this]() {
158 consume(Token::Type::Semicolon);
159 });
160
161 if (match_block_statement()) {
162 consume_semicolon.disarm();
163 return parse_block_statement(parent);
164 }
165 if (match_comment()) {
166 consume_semicolon.disarm();
167 return parse_comment(parent);
168 }
169 if (match_variable_declaration()) {
170 return parse_variable_declaration(parent, false);
171 }
172 if (match_expression()) {
173 return parse_expression(parent);
174 }
175 if (match_keyword("return")) {
176 return parse_return_statement(parent);
177 }
178 if (match_keyword("for")) {
179 consume_semicolon.disarm();
180 return parse_for_statement(parent);
181 }
182 if (match_keyword("if")) {
183 consume_semicolon.disarm();
184 return parse_if_statement(parent);
185 } else {
186 error("unexpected statement type"sv);
187 consume_semicolon.disarm();
188 consume();
189 return create_ast_node<InvalidStatement>(parent, position(), position());
190 }
191}
192
193NonnullRefPtr<Comment const> Parser::parse_comment(ASTNode const& parent)
194{
195 auto comment = create_ast_node<Comment>(parent, position(), {});
196 consume(Token::Type::Comment);
197 comment->set_end(position());
198 return comment;
199}
200
201bool Parser::match_block_statement()
202{
203 return peek().type() == Token::Type::LeftCurly;
204}
205
206NonnullRefPtr<BlockStatement const> Parser::parse_block_statement(ASTNode const& parent)
207{
208 LOG_SCOPE();
209 auto block_statement = create_ast_node<BlockStatement>(parent, position(), {});
210 consume(Token::Type::LeftCurly);
211 while (!eof() && peek().type() != Token::Type::RightCurly) {
212 block_statement->add_statement(parse_statement(*block_statement));
213 }
214 consume(Token::Type::RightCurly);
215 block_statement->set_end(position());
216 return block_statement;
217}
218
219bool Parser::match_type()
220{
221 return match_named_type();
222}
223
224bool Parser::match_named_type()
225{
226 save_state();
227 ScopeGuard state_guard = [this] { load_state(); };
228
229 parse_type_qualifiers();
230 if (match_keyword("auto")) {
231 return true;
232 }
233
234 if (match_keyword("struct")) {
235 consume(Token::Type::Keyword); // Consume struct prefix
236 }
237
238 if (!match_name())
239 return false;
240
241 return true;
242}
243
244bool Parser::match_template_arguments()
245{
246 save_state();
247 ScopeGuard state_guard = [this] { load_state(); };
248
249 if (!peek(Token::Type::Less).has_value())
250 return false;
251 consume();
252
253 while (!eof() && peek().type() != Token::Type::Greater) {
254 if (!match_named_type())
255 return false;
256 (void)parse_type(get_dummy_node());
257 }
258
259 return peek().type() == Token::Type::Greater;
260}
261
262Vector<NonnullRefPtr<Type const>> Parser::parse_template_arguments(ASTNode const& parent)
263{
264 LOG_SCOPE();
265
266 consume(Token::Type::Less);
267
268 Vector<NonnullRefPtr<Type const>> template_arguments;
269 while (!eof() && peek().type() != Token::Type::Greater) {
270 template_arguments.append(parse_type(parent));
271 }
272
273 consume(Token::Type::Greater);
274
275 return template_arguments;
276}
277
278bool Parser::match_variable_declaration()
279{
280 LOG_SCOPE();
281 save_state();
282 ScopeGuard state_guard = [this] { load_state(); };
283
284 if (!match_type()) {
285 return false;
286 }
287
288 VERIFY(m_root_node);
289 (void)parse_type(get_dummy_node());
290
291 // Identifier
292 if (!match_name())
293 return false;
294
295 (void)parse_name(get_dummy_node());
296
297 if (match(Token::Type::Equals)) {
298 consume(Token::Type::Equals);
299 if (!match_expression()) {
300 error("initial value of variable is not an expression"sv);
301 return false;
302 }
303 return true;
304 }
305
306 if (match_braced_init_list())
307 (void)parse_braced_init_list(get_dummy_node());
308
309 return match(Token::Type::Semicolon);
310}
311
312NonnullRefPtr<VariableDeclaration const> Parser::parse_variable_declaration(ASTNode const& parent, bool expect_semicolon)
313{
314 LOG_SCOPE();
315 auto var = create_ast_node<VariableDeclaration>(parent, position(), {});
316 if (!match_variable_declaration()) {
317 error("unexpected token for variable type"sv);
318 var->set_end(position());
319 return var;
320 }
321 var->set_type(parse_type(var));
322 auto name = parse_name(*var);
323 RefPtr<Expression const> initial_value;
324
325 if (match(Token::Type::Equals)) {
326 consume(Token::Type::Equals);
327 initial_value = parse_expression(var);
328 }
329
330 if (match_braced_init_list()) {
331 initial_value = parse_braced_init_list(var);
332 }
333
334 if (expect_semicolon)
335 consume(Token::Type::Semicolon);
336
337 var->set_end(position());
338 var->set_name(name);
339 var->set_initial_value(move(initial_value));
340
341 return var;
342}
343
344NonnullRefPtr<Expression const> Parser::parse_expression(ASTNode const& parent)
345{
346 LOG_SCOPE();
347 auto expression = parse_primary_expression(parent);
348 // TODO: remove eof() logic, should still work without it
349 if (eof() || match(Token::Type::Semicolon)) {
350 return expression;
351 }
352
353 Vector<NonnullRefPtr<Expression const>> secondary_expressions;
354
355 while (match_secondary_expression()) {
356 // FIXME: Handle operator precedence
357 expression = parse_secondary_expression(parent, expression);
358 secondary_expressions.append(expression);
359 }
360
361 for (size_t i = 0; secondary_expressions.size() != 0 && i < secondary_expressions.size() - 1; ++i) {
362 const_cast<Expression&>(*secondary_expressions[i]).set_parent(secondary_expressions[i + 1]);
363 }
364
365 return expression;
366}
367
368bool Parser::match_secondary_expression()
369{
370 auto type = peek().type();
371 return type == Token::Type::Plus
372 || type == Token::Type::PlusEquals
373 || type == Token::Type::Minus
374 || type == Token::Type::MinusEquals
375 || type == Token::Type::Asterisk
376 || type == Token::Type::AsteriskEquals
377 || type == Token::Type::Percent
378 || type == Token::Type::PercentEquals
379 || type == Token::Type::Equals
380 || type == Token::Type::Greater
381 || type == Token::Type::GreaterEquals
382 || type == Token::Type::Less
383 || type == Token::Type::LessEquals
384 || type == Token::Type::Dot
385 || type == Token::Type::PlusPlus
386 || type == Token::Type::MinusMinus
387 || type == Token::Type::And
388 || type == Token::Type::AndEquals
389 || type == Token::Type::Pipe
390 || type == Token::Type::PipeEquals
391 || type == Token::Type::Caret
392 || type == Token::Type::CaretEquals
393 || type == Token::Type::LessLess
394 || type == Token::Type::LessLessEquals
395 || type == Token::Type::GreaterGreater
396 || type == Token::Type::GreaterGreaterEquals
397 || type == Token::Type::EqualsEquals
398 || type == Token::Type::AndAnd
399 || type == Token::Type::PipePipe
400 || type == Token::Type::ExclamationMarkEquals
401 || type == Token::Type::Arrow
402 || type == Token::Type::LeftParen;
403}
404
405NonnullRefPtr<Expression const> Parser::parse_primary_expression(ASTNode const& parent)
406{
407 LOG_SCOPE();
408 // TODO: remove eof() logic, should still work without it
409 if (eof()) {
410 auto node = create_ast_node<Identifier>(parent, position(), position());
411 return node;
412 }
413
414 if (match_unary_expression())
415 return parse_unary_expression(parent);
416
417 if (match_literal()) {
418 return parse_literal(parent);
419 }
420
421 if (match_cpp_cast_expression())
422 return parse_cpp_cast_expression(parent);
423
424 if (match_c_style_cast_expression())
425 return parse_c_style_cast_expression(parent);
426
427 if (match_sizeof_expression())
428 return parse_sizeof_expression(parent);
429
430 if (match_braced_init_list())
431 return parse_braced_init_list(parent);
432
433 if (match_name()) {
434 return parse_name(parent);
435 }
436
437 error("could not parse primary expression"sv);
438 auto token = consume();
439 return create_ast_node<InvalidExpression>(parent, token.start(), token.end());
440}
441
442bool Parser::match_literal()
443{
444 switch (peek().type()) {
445 case Token::Type::Integer:
446 return true;
447 case Token::Type::SingleQuotedString:
448 return true;
449 case Token::Type::DoubleQuotedString:
450 return true;
451 case Token::Type::Float:
452 return true;
453 case Token::Type::Keyword: {
454 return match_boolean_literal() || peek().text() == "nullptr";
455 }
456 default:
457 return false;
458 }
459}
460
461bool Parser::match_unary_expression()
462{
463 auto type = peek().type();
464 return type == Token::Type::PlusPlus
465 || type == Token::Type::MinusMinus
466 || type == Token::Type::ExclamationMark
467 || type == Token::Type::Tilde
468 || type == Token::Type::Plus
469 || type == Token::Type::Minus
470 || type == Token::Type::And;
471}
472
473NonnullRefPtr<UnaryExpression const> Parser::parse_unary_expression(ASTNode const& parent)
474{
475 auto unary_exp = create_ast_node<UnaryExpression>(parent, position(), {});
476 auto op_token = consume();
477 UnaryOp op { UnaryOp::Invalid };
478 switch (op_token.type()) {
479 case Token::Type::Minus:
480 op = UnaryOp::Minus;
481 break;
482 case Token::Type::Plus:
483 op = UnaryOp::Plus;
484 break;
485 case Token::Type::ExclamationMark:
486 op = UnaryOp::Not;
487 break;
488 case Token::Type::Tilde:
489 op = UnaryOp::BitwiseNot;
490 break;
491 case Token::Type::PlusPlus:
492 op = UnaryOp::PlusPlus;
493 break;
494 case Token::Type::And:
495 op = UnaryOp::Address;
496 break;
497 default:
498 break;
499 }
500 unary_exp->set_op(op);
501 auto lhs = parse_expression(*unary_exp);
502 unary_exp->set_lhs(lhs);
503 unary_exp->set_end(lhs->end());
504 return unary_exp;
505}
506
507NonnullRefPtr<Expression const> Parser::parse_literal(ASTNode const& parent)
508{
509 switch (peek().type()) {
510 case Token::Type::Integer: {
511 auto token = consume();
512 return create_ast_node<NumericLiteral>(parent, token.start(), token.end(), text_of_token(token));
513 }
514 case Token::Type::SingleQuotedString:
515 [[fallthrough]];
516 case Token::Type::DoubleQuotedString:
517 return parse_string_literal(parent);
518 case Token::Type::Keyword: {
519 if (match_boolean_literal())
520 return parse_boolean_literal(parent);
521 if (peek().text() == "nullptr") {
522 auto token = consume();
523 return create_ast_node<NullPointerLiteral>(parent, token.start(), token.end());
524 }
525 [[fallthrough]];
526 }
527 default: {
528 error("could not parse literal"sv);
529 auto token = consume();
530 return create_ast_node<InvalidExpression>(parent, token.start(), token.end());
531 }
532 }
533}
534
535NonnullRefPtr<Expression const> Parser::parse_secondary_expression(ASTNode const& parent, NonnullRefPtr<Expression const> lhs)
536{
537 LOG_SCOPE();
538 switch (peek().type()) {
539 case Token::Type::Plus:
540 return parse_binary_expression(parent, lhs, BinaryOp::Addition);
541 case Token::Type::Less:
542 return parse_binary_expression(parent, lhs, BinaryOp::LessThan);
543 case Token::Type::EqualsEquals:
544 return parse_binary_expression(parent, lhs, BinaryOp::EqualsEquals);
545 case Token::Type::ExclamationMarkEquals:
546 return parse_binary_expression(parent, lhs, BinaryOp::NotEqual);
547 case Token::Type::And:
548 return parse_binary_expression(parent, lhs, BinaryOp::BitwiseAnd);
549 case Token::Type::AndAnd:
550 return parse_binary_expression(parent, lhs, BinaryOp::LogicalAnd);
551 case Token::Type::Pipe:
552 return parse_binary_expression(parent, lhs, BinaryOp::BitwiseOr);
553 case Token::Type::PipePipe:
554 return parse_binary_expression(parent, lhs, BinaryOp::LogicalOr);
555 case Token::Type::Arrow:
556 return parse_binary_expression(parent, lhs, BinaryOp::Arrow);
557 case Token::Type::Equals:
558 return parse_assignment_expression(parent, lhs, AssignmentOp::Assignment);
559 case Token::Type::Dot: {
560 consume();
561 auto exp = create_ast_node<MemberExpression>(parent, lhs->start(), {});
562 const_cast<Expression&>(*lhs).set_parent(*exp);
563 exp->set_object(move(lhs));
564 auto identifier_token = consume(Token::Type::Identifier);
565 exp->set_property(create_ast_node<Identifier>(*exp, identifier_token.start(), identifier_token.end(), identifier_token.text()));
566 exp->set_end(position());
567 return exp;
568 }
569 case Token::Type::LeftParen: {
570 consume();
571 auto func = create_ast_node<FunctionCall>(parent, lhs->start(), {});
572 const_cast<Expression&>(*lhs).set_parent(*func);
573 func->set_callee(move(lhs));
574 while (peek().type() != Token::Type::RightParen && !eof()) {
575 func->add_argument(parse_expression(*func));
576 if (peek().type() == Token::Type::Comma)
577 consume(Token::Type::Comma);
578 }
579 consume(Token::Type::RightParen);
580 func->set_end(position());
581 return func;
582 }
583 default: {
584 error(DeprecatedString::formatted("unexpected operator for expression. operator: {}", peek().to_deprecated_string()));
585 auto token = consume();
586 return create_ast_node<InvalidExpression>(parent, token.start(), token.end());
587 }
588 }
589}
590
591NonnullRefPtr<BinaryExpression const> Parser::parse_binary_expression(ASTNode const& parent, NonnullRefPtr<Expression const> lhs, BinaryOp op)
592{
593 consume(); // Operator
594 auto exp = create_ast_node<BinaryExpression>(parent, lhs->start(), {});
595 const_cast<Expression&>(*lhs).set_parent(*exp);
596 exp->set_op(op);
597 exp->set_lhs(move(lhs));
598 auto rhs = parse_expression(exp);
599 exp->set_end(rhs->end());
600 exp->set_rhs(move(rhs));
601 return exp;
602}
603
604NonnullRefPtr<AssignmentExpression const> Parser::parse_assignment_expression(ASTNode const& parent, NonnullRefPtr<Expression const> lhs, AssignmentOp op)
605{
606 consume(); // Operator
607 auto exp = create_ast_node<AssignmentExpression>(parent, lhs->start(), {});
608 const_cast<Expression&>(*lhs).set_parent(*exp);
609 exp->set_op(op);
610 exp->set_lhs(move(lhs));
611 auto rhs = parse_expression(exp);
612 exp->set_end(rhs->end());
613 exp->set_rhs(move(rhs));
614 return exp;
615}
616
617Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit()
618{
619 if (match_function_declaration())
620 return DeclarationType::Function;
621 if (match_enum_declaration())
622 return DeclarationType::Enum;
623 if (match_class_declaration())
624 return DeclarationType::Class;
625 if (match_namespace_declaration())
626 return DeclarationType::Namespace;
627 if (match_variable_declaration())
628 return DeclarationType::Variable;
629 if (match_using_namespace_declaration())
630 return DeclarationType::UsingNamespace;
631 return {};
632}
633
634Optional<Parser::DeclarationType> Parser::match_class_member(StringView class_name)
635{
636 if (match_function_declaration())
637 return DeclarationType::Function;
638 if (match_enum_declaration())
639 return DeclarationType::Enum;
640 if (match_class_declaration())
641 return DeclarationType::Class;
642 if (match_variable_declaration())
643 return DeclarationType::Variable;
644 if (match_constructor(class_name))
645 return DeclarationType::Constructor;
646 if (match_destructor(class_name))
647 return DeclarationType::Destructor;
648 return {};
649}
650
651bool Parser::match_enum_declaration()
652{
653 save_state();
654 ScopeGuard state_guard = [this] { load_state(); };
655
656 if (!match_keyword("enum"))
657 return false;
658
659 consume(Token::Type::Keyword);
660
661 if (match_keyword("class"))
662 consume(Token::Type::Keyword);
663
664 if (!match(Token::Type::Identifier))
665 return false;
666
667 consume(Token::Type::Identifier);
668
669 return match(Token::Type::LeftCurly);
670}
671
672bool Parser::match_class_declaration()
673{
674 save_state();
675 ScopeGuard state_guard = [this] { load_state(); };
676
677 if (!match_keyword("struct") && !match_keyword("class"))
678 return false;
679
680 consume(Token::Type::Keyword);
681
682 if (!match(Token::Type::Identifier))
683 return false;
684
685 consume(Token::Type::Identifier);
686
687 auto has_final = match_keyword("final");
688
689 if (peek(has_final ? 1 : 0).type() == Token::Type::Colon) {
690 if (has_final)
691 consume();
692
693 do {
694 consume();
695
696 while (match_keyword("private") || match_keyword("public") || match_keyword("protected") || match_keyword("virtual"))
697 consume();
698
699 if (!match_name())
700 return false;
701 (void)parse_name(get_dummy_node());
702 } while (peek().type() == Token::Type::Comma);
703 }
704
705 return match(Token::Type::LeftCurly);
706}
707
708bool Parser::match_namespace_declaration()
709{
710 return match_keyword("namespace");
711}
712
713bool Parser::match_function_declaration()
714{
715 save_state();
716 ScopeGuard state_guard = [this] { load_state(); };
717
718 parse_function_qualifiers();
719
720 if (!match_type())
721 return false;
722
723 VERIFY(m_root_node);
724 (void)parse_type(get_dummy_node());
725
726 if (!match_name())
727 return false;
728
729 (void)parse_name(get_dummy_node());
730
731 if (!peek(Token::Type::LeftParen).has_value())
732 return false;
733 consume();
734
735 while (consume().type() != Token::Type::RightParen && !eof()) { };
736
737 while (match_keyword("const") || match_keyword("override"))
738 consume();
739
740 if (peek(Token::Type::Semicolon).has_value() || peek(Token::Type::LeftCurly).has_value())
741 return true;
742
743 if (match_attribute_specification()) {
744 consume_attribute_specification();
745 return peek(Token::Type::Semicolon).has_value();
746 }
747
748 return false;
749}
750
751Optional<Vector<NonnullRefPtr<Parameter const>>> Parser::parse_parameter_list(ASTNode const& parent)
752{
753 LOG_SCOPE();
754 Vector<NonnullRefPtr<Parameter const>> parameters;
755 while (peek().type() != Token::Type::RightParen && !eof()) {
756 if (match_ellipsis()) {
757 auto param = create_ast_node<Parameter>(parent, position(), {}, RefPtr<Name> {});
758 consume(Token::Type::Dot);
759 consume(Token::Type::Dot);
760 auto last_dot = consume(Token::Type::Dot);
761 param->set_ellipsis(true);
762 param->set_end(last_dot.end());
763 parameters.append(move(param));
764 } else {
765 auto type = parse_type(parent);
766
767 RefPtr<Name const> name;
768 if (match_name()) {
769 name = parse_name(parent);
770 }
771
772 auto param = create_ast_node<Parameter>(parent, type->start(), !name.is_null() ? name->end() : type->end(), name);
773 const_cast<Type&>(*type).set_parent(*param.ptr());
774
775 param->set_type(move(type));
776 parameters.append(move(param));
777 }
778
779 if (peek(Token::Type::Comma).has_value())
780 consume(Token::Type::Comma);
781 }
782 return parameters;
783}
784
785bool Parser::match_comment()
786{
787 return match(Token::Type::Comment);
788}
789
790bool Parser::match_whitespace()
791{
792 return match(Token::Type::Whitespace);
793}
794
795bool Parser::match_preprocessor()
796{
797 return match(Token::Type::PreprocessorStatement) || match(Token::Type::IncludeStatement);
798}
799
800void Parser::consume_preprocessor()
801{
802 LOG_SCOPE();
803 switch (peek().type()) {
804 case Token::Type::PreprocessorStatement:
805 consume();
806 break;
807 case Token::Type::IncludeStatement:
808 consume();
809 consume(Token::Type::IncludePath);
810 break;
811 default:
812 error("unexpected token while parsing preprocessor statement"sv);
813 consume();
814 }
815}
816
817Optional<Token> Parser::consume_whitespace()
818{
819 LOG_SCOPE();
820 return consume(Token::Type::Whitespace);
821}
822
823Token Parser::consume(Token::Type type)
824{
825 auto token = consume();
826 if (token.type() != type)
827 error(DeprecatedString::formatted("expected {} at {}:{}, found: {}", Token::type_to_string(type), token.start().line, token.start().column, Token::type_to_string(token.type())));
828 return token;
829}
830
831bool Parser::match(Token::Type type)
832{
833 return peek().type() == type;
834}
835
836Token Parser::consume()
837{
838 if (eof()) {
839 error("C++ Parser: out of tokens"sv);
840 return { Token::Type::EOF_TOKEN, position(), position(), {} };
841 }
842 return m_tokens[m_state.token_index++];
843}
844
845Token Parser::peek(size_t offset) const
846{
847 if (m_state.token_index + offset >= m_tokens.size())
848 return { Token::Type::EOF_TOKEN, position(), position(), {} };
849 return m_tokens[m_state.token_index + offset];
850}
851
852Optional<Token> Parser::peek(Token::Type type) const
853{
854 auto token = peek();
855 if (token.type() == type)
856 return token;
857 return {};
858}
859
860void Parser::save_state()
861{
862 m_saved_states.append(m_state);
863 m_state.state_nodes.clear();
864}
865
866void Parser::load_state()
867{
868 m_state = m_saved_states.take_last();
869}
870
871StringView Parser::text_of_token(Cpp::Token const& token) const
872{
873 return token.text();
874}
875
876DeprecatedString Parser::text_of_node(ASTNode const& node) const
877{
878 return text_in_range(node.start(), node.end());
879}
880
881DeprecatedString Parser::text_in_range(Position start, Position end) const
882{
883 StringBuilder builder;
884 for (auto token : tokens_in_range(start, end)) {
885 builder.append(token.text());
886 }
887 return builder.to_deprecated_string();
888}
889
890Vector<Token> Parser::tokens_in_range(Position start, Position end) const
891{
892 auto start_token_index = index_of_token_at(start);
893 auto end_node_index = index_of_token_at(end);
894 VERIFY(start_token_index.has_value());
895 VERIFY(end_node_index.has_value());
896
897 Vector<Token> tokens;
898 for (size_t i = start_token_index.value(); i <= end_node_index.value(); ++i) {
899 tokens.append(m_tokens[i]);
900 }
901 return tokens;
902}
903
904void Parser::error(StringView message)
905{
906 LOG_SCOPE();
907
908 if (!m_saved_states.is_empty())
909 return;
910
911 if (message.is_null() || message.is_empty())
912 message = "<empty>"sv;
913 DeprecatedString formatted_message;
914 if (m_state.token_index >= m_tokens.size()) {
915 formatted_message = DeprecatedString::formatted("C++ Parsed error on EOF.{}", message);
916 } else {
917 formatted_message = DeprecatedString::formatted("C++ Parser error: {}. token: {} ({}:{})",
918 message,
919 m_state.token_index < m_tokens.size() ? text_of_token(m_tokens[m_state.token_index]) : "EOF"sv,
920 m_tokens[m_state.token_index].start().line,
921 m_tokens[m_state.token_index].start().column);
922 }
923
924 m_errors.append(formatted_message);
925}
926
927bool Parser::match_expression()
928{
929 return match_literal()
930 || match_name()
931 || match_unary_expression()
932 || match_cpp_cast_expression()
933 || match_c_style_cast_expression()
934 || match_sizeof_expression()
935 || match_braced_init_list();
936}
937
938bool Parser::eof() const
939{
940 return m_state.token_index >= m_tokens.size();
941}
942
943Position Parser::position() const
944{
945 if (m_tokens.is_empty())
946 return {};
947
948 if (eof())
949 return m_tokens.last().end();
950
951 return peek().start();
952}
953
954Position Parser::previous_token_end() const
955{
956 if (m_state.token_index < 1)
957 return {};
958 return m_tokens[m_state.token_index - 1].end();
959}
960
961RefPtr<ASTNode const> Parser::node_at(Position pos) const
962{
963 VERIFY(m_saved_states.is_empty());
964 auto index = index_of_node_at(pos);
965 if (!index.has_value())
966 return nullptr;
967 return m_nodes[index.value()];
968}
969
970Optional<size_t> Parser::index_of_node_at(Position pos) const
971{
972 VERIFY(!m_tokens.is_empty());
973 VERIFY(m_saved_states.is_empty());
974 Optional<size_t> match_node_index;
975
976 auto node_span = [](ASTNode const& node) {
977 VERIFY(node.end().line >= node.start().line);
978 VERIFY((node.end().line > node.start().line) || (node.end().column >= node.start().column));
979 return Position { node.end().line - node.start().line, node.start().line != node.end().line ? 0 : node.end().column - node.start().column };
980 };
981
982 for (size_t node_index = 0; node_index < m_nodes.size(); ++node_index) {
983 auto& node = m_nodes[node_index];
984 if (node->start() > pos || node->end() < pos)
985 continue;
986
987 if (!match_node_index.has_value() || (node_span(node) <= node_span(m_nodes[match_node_index.value()])))
988 match_node_index = node_index;
989 }
990 return match_node_index;
991}
992
993Optional<Token> Parser::token_at(Position pos) const
994{
995 auto index = index_of_token_at(pos);
996 if (!index.has_value())
997 return {};
998 return m_tokens[index.value()];
999}
1000
1001Optional<size_t> Parser::index_of_token_at(Position pos) const
1002{
1003 for (size_t token_index = 0; token_index < m_tokens.size(); ++token_index) {
1004 auto token = m_tokens[token_index];
1005 if (token.start() > pos || token.end() < pos)
1006 continue;
1007 return token_index;
1008 }
1009 return {};
1010}
1011
1012void Parser::print_tokens() const
1013{
1014 for (auto& token : m_tokens) {
1015 outln("{}", token.to_deprecated_string());
1016 }
1017}
1018
1019Vector<CodeComprehension::TodoEntry> Parser::get_todo_entries() const
1020{
1021 Vector<CodeComprehension::TodoEntry> ret;
1022 for (auto& token : m_tokens) {
1023 if (token.type() == Token::Type::Comment) {
1024 if (token.text().contains("TODO"sv) || token.text().contains("FIXME"sv)) {
1025 ret.append({ token.text(), m_filename, token.start().line, token.start().column });
1026 }
1027 }
1028 }
1029 return ret;
1030}
1031
1032NonnullRefPtr<StringLiteral const> Parser::parse_string_literal(ASTNode const& parent)
1033{
1034 LOG_SCOPE();
1035 Optional<size_t> start_token_index;
1036 Optional<size_t> end_token_index;
1037 while (!eof()) {
1038 auto token = peek();
1039 if (token.type() != Token::Type::DoubleQuotedString && token.type() != Token::Type::SingleQuotedString && token.type() != Token::Type::EscapeSequence) {
1040 VERIFY(start_token_index.has_value());
1041 end_token_index = m_state.token_index - 1;
1042 break;
1043 }
1044 if (!start_token_index.has_value())
1045 start_token_index = m_state.token_index;
1046 consume();
1047 }
1048
1049 // String was not terminated
1050 if (!end_token_index.has_value()) {
1051 end_token_index = m_tokens.size() - 1;
1052 }
1053
1054 VERIFY(start_token_index.has_value());
1055 VERIFY(end_token_index.has_value());
1056
1057 Token start_token = m_tokens[start_token_index.value()];
1058 Token end_token = m_tokens[end_token_index.value()];
1059
1060 auto text = text_in_range(start_token.start(), end_token.end());
1061 auto string_literal = create_ast_node<StringLiteral>(parent, start_token.start(), end_token.end());
1062 string_literal->set_value(move(text));
1063 return string_literal;
1064}
1065
1066NonnullRefPtr<ReturnStatement const> Parser::parse_return_statement(ASTNode const& parent)
1067{
1068 LOG_SCOPE();
1069 auto return_statement = create_ast_node<ReturnStatement>(parent, position(), {});
1070 consume(Token::Type::Keyword);
1071 if (!peek(Token::Type::Semicolon).has_value()) {
1072 return_statement->set_value(parse_expression(*return_statement));
1073 }
1074 return_statement->set_end(position());
1075 return return_statement;
1076}
1077
1078NonnullRefPtr<EnumDeclaration const> Parser::parse_enum_declaration(ASTNode const& parent)
1079{
1080 LOG_SCOPE();
1081 auto enum_decl = create_ast_node<EnumDeclaration>(parent, position(), {});
1082 consume_keyword("enum");
1083
1084 if (match_keyword("class")) {
1085 consume(Token::Type::Keyword);
1086 enum_decl->set_type(EnumDeclaration::Type::EnumClass);
1087 } else {
1088 enum_decl->set_type(EnumDeclaration::Type::RegularEnum);
1089 }
1090
1091 auto name = parse_name(*enum_decl);
1092 enum_decl->set_name(name);
1093 consume(Token::Type::LeftCurly);
1094 while (!eof() && peek().type() != Token::Type::RightCurly) {
1095 auto name = text_of_token(consume(Token::Type::Identifier));
1096 RefPtr<Expression const> value;
1097 if (peek().type() == Token::Type::Equals) {
1098 consume();
1099 value = parse_expression(enum_decl);
1100 }
1101 enum_decl->add_entry(name, move(value));
1102 if (peek().type() != Token::Type::Comma) {
1103 break;
1104 }
1105 consume(Token::Type::Comma);
1106 }
1107 consume(Token::Type::RightCurly);
1108 consume(Token::Type::Semicolon);
1109 enum_decl->set_end(position());
1110 return enum_decl;
1111}
1112
1113Token Parser::consume_keyword(DeprecatedString const& keyword)
1114{
1115 auto token = consume();
1116 if (token.type() != Token::Type::Keyword) {
1117 error(DeprecatedString::formatted("unexpected token: {}, expected Keyword", token.to_deprecated_string()));
1118 return token;
1119 }
1120 if (text_of_token(token) != keyword) {
1121 error(DeprecatedString::formatted("unexpected keyword: {}, expected {}", text_of_token(token), keyword));
1122 return token;
1123 }
1124 return token;
1125}
1126
1127bool Parser::match_keyword(DeprecatedString const& keyword)
1128{
1129 auto token = peek();
1130 if (token.type() != Token::Type::Keyword) {
1131 return false;
1132 }
1133 if (text_of_token(token) != keyword) {
1134 return false;
1135 }
1136 return true;
1137}
1138
1139NonnullRefPtr<StructOrClassDeclaration const> Parser::parse_class_declaration(ASTNode const& parent)
1140{
1141 LOG_SCOPE();
1142
1143 auto type_token = consume(Token::Type::Keyword);
1144 StructOrClassDeclaration::Type type {};
1145
1146 if (type_token.text() == "struct")
1147 type = StructOrClassDeclaration::Type::Struct;
1148 if (type_token.text() == "class")
1149 type = StructOrClassDeclaration::Type::Class;
1150
1151 auto decl = create_ast_node<StructOrClassDeclaration>(parent, position(), {}, type);
1152
1153 auto name = parse_name(*decl);
1154 decl->set_name(name);
1155
1156 auto has_final = match_keyword("final");
1157
1158 Vector<NonnullRefPtr<Name const>> baseclasses;
1159
1160 // FIXME: Don't ignore this.
1161 if (peek(has_final ? 1 : 0).type() == Token::Type::Colon) {
1162 if (has_final)
1163 consume();
1164
1165 do {
1166 consume();
1167
1168 while (match_keyword("private") || match_keyword("public") || match_keyword("protected") || match_keyword("virtual"))
1169 consume();
1170
1171 baseclasses.append(parse_name(*decl));
1172 } while (peek().type() == Token::Type::Comma);
1173 }
1174
1175 decl->set_baseclasses(move(baseclasses));
1176
1177 consume(Token::Type::LeftCurly);
1178
1179 while (!eof() && peek().type() != Token::Type::RightCurly) {
1180 decl->set_members(parse_class_members(*decl));
1181 }
1182
1183 consume(Token::Type::RightCurly);
1184 consume(Token::Type::Semicolon);
1185 decl->set_end(position());
1186 return decl;
1187}
1188
1189NonnullRefPtr<BooleanLiteral const> Parser::parse_boolean_literal(ASTNode const& parent)
1190{
1191 LOG_SCOPE();
1192 auto token = consume(Token::Type::Keyword);
1193 auto text = text_of_token(token);
1194 // text == "true" || text == "false";
1195 bool value = (text == "true");
1196 return create_ast_node<BooleanLiteral>(parent, token.start(), token.end(), value);
1197}
1198
1199bool Parser::match_boolean_literal()
1200{
1201 auto token = peek();
1202 if (token.type() != Token::Type::Keyword)
1203 return false;
1204 auto text = text_of_token(token);
1205 return text == "true" || text == "false";
1206}
1207
1208NonnullRefPtr<Type const> Parser::parse_type(ASTNode const& parent)
1209{
1210 LOG_SCOPE();
1211
1212 if (!match_named_type()) {
1213 error("expected named named_type"sv);
1214 auto token = consume();
1215 return create_ast_node<NamedType>(parent, token.start(), token.end());
1216 }
1217
1218 auto named_type = create_ast_node<NamedType>(parent, position(), {});
1219
1220 auto qualifiers = parse_type_qualifiers();
1221 named_type->set_qualifiers(move(qualifiers));
1222
1223 if (match_keyword("auto")) {
1224 consume(Token::Type::Keyword);
1225 named_type->set_auto(true);
1226 auto original_qualifiers = named_type->qualifiers();
1227 original_qualifiers.extend(parse_type_qualifiers());
1228 named_type->set_qualifiers(move(original_qualifiers));
1229 named_type->set_end(position());
1230 return named_type;
1231 }
1232
1233 if (match_keyword("struct")) {
1234 consume(Token::Type::Keyword); // Consume struct prefix
1235 }
1236
1237 if (!match_name()) {
1238 named_type->set_end(position());
1239 error(DeprecatedString::formatted("expected name instead of: {}", peek().text()));
1240 return named_type;
1241 }
1242 named_type->set_name(parse_name(*named_type));
1243
1244 auto original_qualifiers = named_type->qualifiers();
1245 original_qualifiers.extend(parse_type_qualifiers());
1246 named_type->set_qualifiers(move(original_qualifiers));
1247
1248 NonnullRefPtr<Type> type = named_type;
1249 while (!eof() && peek().type() == Token::Type::Asterisk) {
1250 type->set_end(position());
1251 auto asterisk = consume();
1252 auto ptr = create_ast_node<Pointer>(parent, type->start(), asterisk.end());
1253 type->set_parent(*ptr);
1254 ptr->set_pointee(type);
1255 ptr->set_qualifiers(parse_type_qualifiers());
1256 ptr->set_end(position());
1257 type = ptr;
1258 }
1259
1260 if (!eof() && (peek().type() == Token::Type::And || peek().type() == Token::Type::AndAnd)) {
1261 type->set_end(position());
1262 auto ref_token = consume();
1263 auto ref = create_ast_node<Reference>(parent, type->start(), ref_token.end(), ref_token.type() == Token::Type::And ? Reference::Kind::Lvalue : Reference::Kind::Rvalue);
1264 type->set_parent(*ref);
1265 ref->set_referenced_type(type);
1266 ref->set_end(position());
1267 type = ref;
1268 }
1269
1270 if (peek().type() == Token::Type::LeftParen) {
1271 type->set_end(previous_token_end());
1272 consume();
1273 auto fn_type = create_ast_node<FunctionType>(parent, type->start(), position());
1274 fn_type->set_return_type(*type);
1275 type->set_parent(*fn_type);
1276 if (auto parameters = parse_parameter_list(*type); parameters.has_value())
1277 fn_type->set_parameters(parameters.release_value());
1278 consume(Token::Type::RightParen);
1279 type = fn_type;
1280 }
1281
1282 type->set_end(previous_token_end());
1283
1284 return type;
1285}
1286
1287NonnullRefPtr<ForStatement const> Parser::parse_for_statement(ASTNode const& parent)
1288{
1289 LOG_SCOPE();
1290 auto for_statement = create_ast_node<ForStatement>(parent, position(), {});
1291 consume(Token::Type::Keyword);
1292 consume(Token::Type::LeftParen);
1293 if (peek().type() != Token::Type::Semicolon)
1294 for_statement->set_init(parse_variable_declaration(*for_statement, false));
1295 consume(Token::Type::Semicolon);
1296
1297 if (peek().type() != Token::Type::Semicolon)
1298 for_statement->set_test(parse_expression(*for_statement));
1299 consume(Token::Type::Semicolon);
1300
1301 if (peek().type() != Token::Type::RightParen)
1302 for_statement->set_update(parse_expression(*for_statement));
1303 consume(Token::Type::RightParen);
1304
1305 for_statement->set_body(parse_statement(*for_statement));
1306
1307 for_statement->set_end(for_statement->body()->end());
1308 return for_statement;
1309}
1310
1311NonnullRefPtr<IfStatement const> Parser::parse_if_statement(ASTNode const& parent)
1312{
1313 LOG_SCOPE();
1314 auto if_statement = create_ast_node<IfStatement>(parent, position(), {});
1315 consume(Token::Type::Keyword);
1316 consume(Token::Type::LeftParen);
1317 if_statement->set_predicate(parse_expression(*if_statement));
1318 consume(Token::Type::RightParen);
1319 if_statement->set_then_statement(parse_statement(*if_statement));
1320 if (match_keyword("else")) {
1321 consume(Token::Type::Keyword);
1322 if_statement->set_else_statement(parse_statement(*if_statement));
1323 if_statement->set_end(if_statement->else_statement()->end());
1324 } else {
1325 if_statement->set_end(if_statement->then_statement()->end());
1326 }
1327 return if_statement;
1328}
1329Vector<StringView> Parser::parse_type_qualifiers()
1330{
1331 LOG_SCOPE();
1332 Vector<StringView> qualifiers;
1333 while (!eof()) {
1334 auto token = peek();
1335 if (token.type() != Token::Type::Keyword)
1336 break;
1337 auto text = text_of_token(token);
1338 if (text == "static" || text == "const" || text == "extern") {
1339 qualifiers.append(text);
1340 consume();
1341 } else {
1342 break;
1343 }
1344 }
1345 return qualifiers;
1346}
1347
1348Vector<StringView> Parser::parse_function_qualifiers()
1349{
1350 LOG_SCOPE();
1351 Vector<StringView> qualifiers;
1352 while (!eof()) {
1353 auto token = peek();
1354 if (token.type() != Token::Type::Keyword)
1355 break;
1356 auto text = text_of_token(token);
1357 if (text == "static" || text == "inline" || text == "extern" || text == "virtual") {
1358 qualifiers.append(text);
1359 consume();
1360 } else {
1361 break;
1362 }
1363 }
1364 return qualifiers;
1365}
1366
1367bool Parser::match_attribute_specification()
1368{
1369 return text_of_token(peek()) == "__attribute__";
1370}
1371void Parser::consume_attribute_specification()
1372{
1373 consume(); // __attribute__
1374 consume(Token::Type::LeftParen);
1375 size_t left_count = 1;
1376 while (!eof()) {
1377 auto token = consume();
1378 if (token.type() == Token::Type::LeftParen) {
1379 ++left_count;
1380 }
1381 if (token.type() == Token::Type::RightParen) {
1382 --left_count;
1383 }
1384 if (left_count == 0)
1385 return;
1386 }
1387}
1388
1389bool Parser::match_ellipsis()
1390{
1391 if (m_state.token_index > m_tokens.size() - 3)
1392 return false;
1393 return peek().type() == Token::Type::Dot && peek(1).type() == Token::Type::Dot && peek(2).type() == Token::Type::Dot;
1394}
1395
1396NonnullRefPtr<NamespaceDeclaration const> Parser::parse_namespace_declaration(ASTNode const& parent, bool is_nested_namespace)
1397{
1398 auto namespace_decl = create_ast_node<NamespaceDeclaration>(parent, position(), {});
1399
1400 if (!is_nested_namespace)
1401 consume(Token::Type::Keyword);
1402
1403 auto name = parse_name(*namespace_decl);
1404 namespace_decl->set_name(name);
1405
1406 if (peek().type() == Token::Type::ColonColon) {
1407 consume(Token::Type::ColonColon);
1408 namespace_decl->add_declaration(parse_namespace_declaration(*namespace_decl, true));
1409 namespace_decl->set_end(position());
1410 return namespace_decl;
1411 }
1412
1413 consume(Token::Type::LeftCurly);
1414 while (!eof() && peek().type() != Token::Type::RightCurly) {
1415 auto declaration = parse_single_declaration_in_translation_unit(*namespace_decl);
1416 if (declaration) {
1417 namespace_decl->add_declaration(declaration.release_nonnull());
1418 } else {
1419 error("unexpected token"sv);
1420 consume();
1421 }
1422 }
1423 consume(Token::Type::RightCurly);
1424 namespace_decl->set_end(position());
1425 return namespace_decl;
1426}
1427
1428bool Parser::match_name()
1429{
1430 auto type = peek().type();
1431 return type == Token::Type::Identifier || type == Token::Type::KnownType;
1432}
1433
1434NonnullRefPtr<Name const> Parser::parse_name(ASTNode const& parent)
1435{
1436 LOG_SCOPE();
1437 NonnullRefPtr<Name> name_node = create_ast_node<Name>(parent, position(), {});
1438 while (!eof() && (peek().type() == Token::Type::Identifier || peek().type() == Token::Type::KnownType) && peek(1).type() == Token::Type::ColonColon) {
1439 auto token = consume();
1440 name_node->add_to_scope(create_ast_node<Identifier>(*name_node, token.start(), token.end(), token.text()));
1441 consume(Token::Type::ColonColon);
1442 }
1443
1444 if (peek().type() == Token::Type::Identifier || peek().type() == Token::Type::KnownType) {
1445 auto token = consume();
1446 name_node->set_name(create_ast_node<Identifier>(*name_node, token.start(), token.end(), token.text()));
1447 } else {
1448 name_node->set_end(position());
1449 return name_node;
1450 }
1451
1452 if (match_template_arguments()) {
1453 consume(Token::Type::Less);
1454 NonnullRefPtr<TemplatizedName> templatized_name = create_ast_node<TemplatizedName>(parent, name_node->start(), {});
1455 templatized_name->set_name(name_node->name());
1456 templatized_name->set_scope(name_node->scope());
1457 name_node->set_end(position());
1458 name_node = templatized_name;
1459 while (peek().type() != Token::Type::Greater && !eof()) {
1460 templatized_name->add_template_argument(parse_type(*templatized_name));
1461 if (peek().type() == Token::Type::Comma)
1462 consume(Token::Type::Comma);
1463 }
1464 consume(Token::Type::Greater);
1465 }
1466
1467 name_node->set_end(previous_token_end());
1468 return name_node;
1469}
1470
1471bool Parser::match_cpp_cast_expression()
1472{
1473 save_state();
1474 ScopeGuard state_guard = [this] { load_state(); };
1475
1476 auto token = consume();
1477 if (token.type() != Token::Type::Keyword)
1478 return false;
1479
1480 auto text = token.text();
1481 if (text == "static_cast" || text == "reinterpret_cast" || text == "dynamic_cast" || text == "const_cast")
1482 return true;
1483 return false;
1484}
1485
1486bool Parser::match_c_style_cast_expression()
1487{
1488 save_state();
1489 ScopeGuard state_guard = [this] { load_state(); };
1490
1491 if (consume().type() != Token::Type::LeftParen)
1492 return false;
1493
1494 if (!match_type())
1495 return false;
1496 (void)parse_type(get_dummy_node());
1497
1498 if (consume().type() != Token::Type::RightParen)
1499 return false;
1500
1501 if (!match_expression())
1502 return false;
1503
1504 return true;
1505}
1506
1507NonnullRefPtr<CStyleCastExpression const> Parser::parse_c_style_cast_expression(ASTNode const& parent)
1508{
1509 auto parse_exp = create_ast_node<CStyleCastExpression>(parent, position(), {});
1510
1511 consume(Token::Type::LeftParen);
1512 parse_exp->set_type(parse_type(*parse_exp));
1513 consume(Token::Type::RightParen);
1514 parse_exp->set_expression(parse_expression(*parse_exp));
1515 parse_exp->set_end(position());
1516
1517 return parse_exp;
1518}
1519
1520NonnullRefPtr<CppCastExpression const> Parser::parse_cpp_cast_expression(ASTNode const& parent)
1521{
1522 auto cast_expression = create_ast_node<CppCastExpression>(parent, position(), {});
1523
1524 cast_expression->set_cast_type(consume(Token::Type::Keyword).text());
1525
1526 consume(Token::Type::Less);
1527 cast_expression->set_type(parse_type(*cast_expression));
1528 consume(Token::Type::Greater);
1529
1530 consume(Token::Type::LeftParen);
1531 cast_expression->set_expression(parse_expression(*cast_expression));
1532 consume(Token::Type::RightParen);
1533
1534 cast_expression->set_end(position());
1535
1536 return cast_expression;
1537}
1538
1539bool Parser::match_sizeof_expression()
1540{
1541 return match_keyword("sizeof");
1542}
1543
1544NonnullRefPtr<SizeofExpression const> Parser::parse_sizeof_expression(ASTNode const& parent)
1545{
1546 auto exp = create_ast_node<SizeofExpression>(parent, position(), {});
1547 consume(Token::Type::Keyword);
1548 consume(Token::Type::LeftParen);
1549 exp->set_type(parse_type(parent));
1550 consume(Token::Type::RightParen);
1551 exp->set_end(position());
1552 return exp;
1553}
1554
1555bool Parser::match_braced_init_list()
1556{
1557 return match(Token::Type::LeftCurly);
1558}
1559
1560NonnullRefPtr<BracedInitList const> Parser::parse_braced_init_list(ASTNode const& parent)
1561{
1562 auto init_list = create_ast_node<BracedInitList>(parent, position(), {});
1563
1564 consume(Token::Type::LeftCurly);
1565 while (!eof() && peek().type() != Token::Type::RightCurly) {
1566 init_list->add_expression(parse_expression(*init_list));
1567 }
1568 consume(Token::Type::RightCurly);
1569 init_list->set_end(position());
1570 return init_list;
1571}
1572Vector<NonnullRefPtr<Declaration const>> Parser::parse_class_members(StructOrClassDeclaration& parent)
1573{
1574 auto class_name = parent.full_name();
1575
1576 Vector<NonnullRefPtr<Declaration const>> members;
1577 while (!eof() && peek().type() != Token::Type::RightCurly) {
1578 if (match_access_specifier())
1579 consume_access_specifier(); // FIXME: Do not ignore access specifiers
1580 auto member_type = match_class_member(class_name);
1581 if (member_type.has_value()) {
1582 members.append(parse_declaration(parent, member_type.value()));
1583 } else {
1584 error("Expected class member"sv);
1585 consume();
1586 }
1587 }
1588 return members;
1589}
1590
1591bool Parser::match_access_specifier()
1592{
1593 if (peek(1).type() != Token::Type::Colon)
1594 return false;
1595
1596 return match_keyword("private") || match_keyword("protected") || match_keyword("public");
1597}
1598
1599void Parser::consume_access_specifier()
1600{
1601 consume(Token::Type::Keyword);
1602 consume(Token::Type::Colon);
1603}
1604
1605bool Parser::match_constructor(StringView class_name)
1606{
1607 save_state();
1608 ScopeGuard state_guard = [this] { load_state(); };
1609
1610 auto token = consume();
1611 if (token.text() != class_name)
1612 return false;
1613
1614 if (!peek(Token::Type::LeftParen).has_value())
1615 return false;
1616 consume();
1617
1618 while (consume().type() != Token::Type::RightParen && !eof()) { };
1619
1620 return (peek(Token::Type::Semicolon).has_value() || peek(Token::Type::LeftCurly).has_value());
1621}
1622
1623bool Parser::match_destructor(StringView class_name)
1624{
1625 save_state();
1626 ScopeGuard state_guard = [this] { load_state(); };
1627
1628 if (match_keyword("virtual"))
1629 consume();
1630
1631 if (!match(Token::Type::Tilde))
1632 return false;
1633 consume();
1634
1635 auto token = peek();
1636
1637 if (token.text() != class_name)
1638 return false;
1639 consume();
1640
1641 if (!peek(Token::Type::LeftParen).has_value())
1642 return false;
1643 consume();
1644
1645 while (consume().type() != Token::Type::RightParen && !eof()) { };
1646
1647 if (match_keyword("override"))
1648 consume();
1649
1650 return (peek(Token::Type::Semicolon).has_value() || peek(Token::Type::LeftCurly).has_value());
1651}
1652
1653void Parser::parse_constructor_or_destructor_impl(FunctionDeclaration& func, CtorOrDtor type)
1654{
1655 if (type == CtorOrDtor::Dtor) {
1656 if (match_keyword("virtual"))
1657 func.set_qualifiers({ consume().text() });
1658 consume(Token::Type::Tilde);
1659 }
1660
1661 auto name = parse_name(func);
1662 func.set_name(name);
1663
1664 consume(Token::Type::LeftParen);
1665 auto parameters = parse_parameter_list(func);
1666 if (parameters.has_value()) {
1667 if (type == CtorOrDtor::Dtor && !parameters->is_empty())
1668 error("Destructor declaration that takes parameters"sv);
1669 else
1670 func.set_parameters(parameters.value());
1671 }
1672
1673 consume(Token::Type::RightParen);
1674
1675 if (type == CtorOrDtor::Dtor && match_keyword("override"))
1676 consume();
1677
1678 // TODO: Parse =default, =delete.
1679
1680 RefPtr<FunctionDefinition const> body;
1681 Position ctor_end {};
1682 if (peek(Token::Type::LeftCurly).has_value()) {
1683 body = parse_function_definition(func);
1684 ctor_end = body->end();
1685 } else {
1686 ctor_end = position();
1687 if (match_attribute_specification())
1688 consume_attribute_specification(); // we don't use the value of __attribute__
1689 consume(Token::Type::Semicolon);
1690 }
1691
1692 func.set_definition(move(body));
1693 func.set_end(ctor_end);
1694}
1695
1696NonnullRefPtr<Constructor const> Parser::parse_constructor(ASTNode const& parent)
1697{
1698 auto ctor = create_ast_node<Constructor>(parent, position(), {});
1699 parse_constructor_or_destructor_impl(*ctor, CtorOrDtor::Ctor);
1700 return ctor;
1701}
1702
1703NonnullRefPtr<Destructor const> Parser::parse_destructor(ASTNode const& parent)
1704{
1705 auto ctor = create_ast_node<Destructor>(parent, position(), {});
1706 parse_constructor_or_destructor_impl(*ctor, CtorOrDtor::Dtor);
1707 return ctor;
1708}
1709
1710bool Parser::match_using_namespace_declaration()
1711{
1712 save_state();
1713 ScopeGuard state_guard = [this] { load_state(); };
1714
1715 if (!match_keyword("using"))
1716 return false;
1717 consume();
1718
1719 if (!match_keyword("namespace"))
1720 return false;
1721 consume();
1722
1723 return true;
1724}
1725
1726NonnullRefPtr<UsingNamespaceDeclaration const> Parser::parse_using_namespace_declaration(ASTNode const& parent)
1727{
1728 auto decl = create_ast_node<UsingNamespaceDeclaration>(parent, position(), {});
1729
1730 consume_keyword("using");
1731 consume_keyword("namespace");
1732
1733 auto name = parse_name(*decl);
1734
1735 decl->set_end(position());
1736 consume(Token::Type::Semicolon);
1737
1738 decl->set_name(name);
1739
1740 return decl;
1741}
1742
1743}