| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2021, Itamar S. <itamar8910@gmail.com> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Parser.h"
 | 
					
						
							|  |  |  | #include "AST.h"
 | 
					
						
							| 
									
										
										
										
											2021-02-06 15:48:46 +02:00
										 |  |  | #include <AK/Debug.h>
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | #include <AK/ScopeGuard.h>
 | 
					
						
							|  |  |  | #include <AK/ScopeLogger.h>
 | 
					
						
							|  |  |  | #include <LibCpp/Lexer.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  | #define LOG_SCOPE() ScopeLogger<CPP_DEBUG> logger(String::formatted("'{}' - {} ({})", peek().text(), peek().type_as_string(), m_state.token_index))
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | namespace Cpp { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 17:04:08 +02:00
										 |  |  | Parser::Parser(const StringView& program, const String& filename, Preprocessor::Definitions&& definitions) | 
					
						
							| 
									
										
										
										
											2021-05-07 14:46:11 +03:00
										 |  |  |     : m_preprocessor_definitions(move(definitions)) | 
					
						
							| 
									
										
										
										
											2021-02-20 12:23:53 +02:00
										 |  |  |     , m_filename(filename) | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-12 15:56:30 +02:00
										 |  |  |     initialize_program_tokens(program); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |     if constexpr (CPP_DEBUG) { | 
					
						
							|  |  |  |         dbgln("Tokens:"); | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |         for (size_t i = 0; i < m_tokens.size(); ++i) { | 
					
						
							|  |  |  |             dbgln("{}- {}", i, m_tokens[i].to_string()); | 
					
						
							| 
									
										
										
										
											2021-05-01 21:10:08 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-13 10:37:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 15:56:30 +02:00
										 |  |  | void Parser::initialize_program_tokens(const StringView& program) | 
					
						
							| 
									
										
										
										
											2021-03-12 17:04:08 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-12 15:56:30 +02:00
										 |  |  |     Lexer lexer(program); | 
					
						
							| 
									
										
										
										
											2021-03-12 17:04:08 +02:00
										 |  |  |     for (auto& token : lexer.lex()) { | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |         if (token.type() == Token::Type::Whitespace) | 
					
						
							| 
									
										
										
										
											2021-03-12 17:04:08 +02:00
										 |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |         if (token.type() == Token::Type::Identifier) { | 
					
						
							| 
									
										
										
										
											2021-05-07 14:46:11 +03:00
										 |  |  |             if (auto defined_value = m_preprocessor_definitions.find(text_of_token(token)); defined_value != m_preprocessor_definitions.end()) { | 
					
						
							| 
									
										
										
										
											2021-03-12 17:04:08 +02:00
										 |  |  |                 add_tokens_for_preprocessor(token, defined_value->value); | 
					
						
							| 
									
										
										
										
											2021-03-13 10:37:23 +02:00
										 |  |  |                 m_replaced_preprocessor_tokens.append({ token, defined_value->value }); | 
					
						
							| 
									
										
										
										
											2021-03-12 17:04:08 +02:00
										 |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         m_tokens.append(move(token)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<TranslationUnit> Parser::parse() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-03-16 18:45:51 +01:00
										 |  |  |     if (m_tokens.is_empty()) | 
					
						
							|  |  |  |         return create_root_ast_node({}, {}); | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |     auto unit = create_root_ast_node(m_tokens.first().start(), m_tokens.last().end()); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     unit->set_declarations(parse_declarations_in_translation_unit(*unit)); | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |     return unit; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtrVector<Declaration> Parser::parse_declarations_in_translation_unit(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     NonnullRefPtrVector<Declaration> declarations; | 
					
						
							|  |  |  |     while (!eof()) { | 
					
						
							|  |  |  |         auto declaration = parse_single_declaration_in_translation_unit(parent); | 
					
						
							|  |  |  |         if (declaration) { | 
					
						
							|  |  |  |             declarations.append(declaration.release_nonnull()); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             error("unexpected token"); | 
					
						
							|  |  |  |             consume(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return declarations; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RefPtr<Declaration> Parser::parse_single_declaration_in_translation_unit(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     while (!eof()) { | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         if (match_comment()) { | 
					
						
							|  |  |  |             consume(Token::Type::Comment); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (match_preprocessor()) { | 
					
						
							|  |  |  |             consume_preprocessor(); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |         auto declaration = match_declaration_in_translation_unit(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         if (declaration.has_value()) { | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |             return parse_declaration(parent, declaration.value()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Declaration> Parser::parse_declaration(ASTNode& parent, DeclarationType declaration_type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (declaration_type) { | 
					
						
							|  |  |  |     case DeclarationType::Function: | 
					
						
							|  |  |  |         return parse_function_declaration(parent); | 
					
						
							|  |  |  |     case DeclarationType::Variable: | 
					
						
							|  |  |  |         return parse_variable_declaration(parent); | 
					
						
							|  |  |  |     case DeclarationType::Enum: | 
					
						
							|  |  |  |         return parse_enum_declaration(parent); | 
					
						
							| 
									
										
										
										
											2021-04-19 19:41:43 +03:00
										 |  |  |     case DeclarationType::Class: | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  |         return parse_class_declaration(parent); | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |     case DeclarationType::Namespace: | 
					
						
							|  |  |  |         return parse_namespace_declaration(parent); | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  |     case DeclarationType::Constructor: | 
					
						
							|  |  |  |         return parse_constructor(parent); | 
					
						
							|  |  |  |     case DeclarationType::Destructor: | 
					
						
							|  |  |  |         return parse_destructor(parent); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     default: | 
					
						
							|  |  |  |         error("unexpected declaration type"); | 
					
						
							|  |  |  |         return create_ast_node<InvalidDeclaration>(parent, position(), position()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<FunctionDeclaration> Parser::parse_function_declaration(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto func = create_ast_node<FunctionDeclaration>(parent, position(), {}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     func->set_qualifiers(parse_function_qualifiers()); | 
					
						
							|  |  |  |     func->set_return_type(parse_type(*func)); | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto function_name = consume(Token::Type::Identifier); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     func->set_name(text_of_token(function_name)); | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     consume(Token::Type::LeftParen); | 
					
						
							|  |  |  |     auto parameters = parse_parameter_list(*func); | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  |     if (parameters.has_value()) | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         func->set_parameters(parameters.value()); | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     consume(Token::Type::RightParen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     RefPtr<FunctionDefinition> body; | 
					
						
							|  |  |  |     Position func_end {}; | 
					
						
							|  |  |  |     if (peek(Token::Type::LeftCurly).has_value()) { | 
					
						
							|  |  |  |         body = parse_function_definition(*func); | 
					
						
							|  |  |  |         func_end = body->end(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         func_end = position(); | 
					
						
							| 
									
										
										
										
											2021-03-01 22:32:42 +02:00
										 |  |  |         if (match_attribute_specification()) | 
					
						
							|  |  |  |             consume_attribute_specification(); // we don't use the value of __attribute__
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         consume(Token::Type::Semicolon); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     func->set_definition(move(body)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     func->set_end(func_end); | 
					
						
							|  |  |  |     return func; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<FunctionDefinition> Parser::parse_function_definition(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto func = create_ast_node<FunctionDefinition>(parent, position(), {}); | 
					
						
							|  |  |  |     consume(Token::Type::LeftCurly); | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |     while (!eof() && peek().type() != Token::Type::RightCurly) { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         func->add_statement(parse_statement(func)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     func->set_end(position()); | 
					
						
							|  |  |  |     if (!eof()) | 
					
						
							|  |  |  |         consume(Token::Type::RightCurly); | 
					
						
							|  |  |  |     return func; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Statement> Parser::parse_statement(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |     ArmedScopeGuard consume_semicolon([this]() { | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         consume(Token::Type::Semicolon); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (match_block_statement()) { | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |         consume_semicolon.disarm(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return parse_block_statement(parent); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (match_comment()) { | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |         consume_semicolon.disarm(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return parse_comment(parent); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (match_variable_declaration()) { | 
					
						
							| 
									
										
										
										
											2021-03-27 18:42:32 +03:00
										 |  |  |         return parse_variable_declaration(parent, false); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (match_expression()) { | 
					
						
							|  |  |  |         return parse_expression(parent); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (match_keyword("return")) { | 
					
						
							|  |  |  |         return parse_return_statement(parent); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (match_keyword("for")) { | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |         consume_semicolon.disarm(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return parse_for_statement(parent); | 
					
						
							| 
									
										
										
										
											2021-01-29 12:03:02 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (match_keyword("if")) { | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |         consume_semicolon.disarm(); | 
					
						
							| 
									
										
										
										
											2021-01-29 12:03:02 +02:00
										 |  |  |         return parse_if_statement(parent); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         error("unexpected statement type"); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |         consume_semicolon.disarm(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         consume(); | 
					
						
							|  |  |  |         return create_ast_node<InvalidStatement>(parent, position(), position()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Comment> Parser::parse_comment(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto comment = create_ast_node<Comment>(parent, position(), {}); | 
					
						
							|  |  |  |     consume(Token::Type::Comment); | 
					
						
							|  |  |  |     comment->set_end(position()); | 
					
						
							|  |  |  |     return comment; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_block_statement() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return peek().type() == Token::Type::LeftCurly; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<BlockStatement> Parser::parse_block_statement(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto block_statement = create_ast_node<BlockStatement>(parent, position(), {}); | 
					
						
							|  |  |  |     consume(Token::Type::LeftCurly); | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |     while (!eof() && peek().type() != Token::Type::RightCurly) { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         block_statement->add_statement(parse_statement(*block_statement)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     consume(Token::Type::RightCurly); | 
					
						
							|  |  |  |     block_statement->set_end(position()); | 
					
						
							|  |  |  |     return block_statement; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  | bool Parser::match_type() | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     return match_named_type(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_named_type() | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-28 18:40:45 +02:00
										 |  |  |     parse_type_qualifiers(); | 
					
						
							| 
									
										
										
										
											2021-05-17 10:40:19 +03:00
										 |  |  |     if (match_keyword("auto")) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 10:36:48 +03:00
										 |  |  |     if (match_keyword("struct")) { | 
					
						
							|  |  |  |         consume(Token::Type::Keyword); // Consume struct prefix
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 16:52:35 +03:00
										 |  |  |     if (!match_name()) | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_template_arguments() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!peek(Token::Type::Less).has_value()) | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |     consume(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (!eof() && peek().type() != Token::Type::Greater) { | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |         if (!match_named_type()) | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2021-04-02 13:57:52 +03:00
										 |  |  |         parse_type(get_dummy_node()); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return peek().type() == Token::Type::Greater; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtrVector<Type> Parser::parse_template_arguments(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::Less); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     NonnullRefPtrVector<Type> template_arguments; | 
					
						
							|  |  |  |     while (!eof() && peek().type() != Token::Type::Greater) { | 
					
						
							|  |  |  |         template_arguments.append(parse_type(parent)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::Greater); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return template_arguments; | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_variable_declaration() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |     if (!match_type()) { | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  |     VERIFY(m_root_node); | 
					
						
							| 
									
										
										
										
											2021-04-02 13:57:52 +03:00
										 |  |  |     parse_type(get_dummy_node()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 15:48:46 +02:00
										 |  |  |     // Identifier
 | 
					
						
							| 
									
										
										
										
											2021-07-28 04:05:39 +04:30
										 |  |  |     if (!match_name()) | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-07-28 04:05:39 +04:30
										 |  |  | 
 | 
					
						
							|  |  |  |     parse_name(get_dummy_node()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (match(Token::Type::Equals)) { | 
					
						
							|  |  |  |         consume(Token::Type::Equals); | 
					
						
							|  |  |  |         if (!match_expression()) { | 
					
						
							|  |  |  |             error("initial value of variable is not an expression"); | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-02-06 15:48:46 +02:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  |     if (match_braced_init_list()) | 
					
						
							|  |  |  |         parse_braced_init_list(get_dummy_node()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-06 15:48:46 +02:00
										 |  |  |     return match(Token::Type::Semicolon); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 18:42:32 +03:00
										 |  |  | NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration(ASTNode& parent, bool expect_semicolon) | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto var = create_ast_node<VariableDeclaration>(parent, position(), {}); | 
					
						
							| 
									
										
										
										
											2021-02-28 18:40:45 +02:00
										 |  |  |     if (!match_variable_declaration()) { | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         error("unexpected token for variable type"); | 
					
						
							| 
									
										
										
										
											2021-02-28 18:40:45 +02:00
										 |  |  |         var->set_end(position()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return var; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     var->set_type(parse_type(var)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto identifier_token = consume(Token::Type::Identifier); | 
					
						
							|  |  |  |     RefPtr<Expression> initial_value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (match(Token::Type::Equals)) { | 
					
						
							|  |  |  |         consume(Token::Type::Equals); | 
					
						
							|  |  |  |         initial_value = parse_expression(var); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  |     if (match_braced_init_list()) { | 
					
						
							|  |  |  |         initial_value = parse_braced_init_list(var); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 19:20:20 +03:00
										 |  |  |     if (expect_semicolon) | 
					
						
							| 
									
										
										
										
											2021-03-27 18:42:32 +03:00
										 |  |  |         consume(Token::Type::Semicolon); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     var->set_end(position()); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     var->set_name(text_of_token(identifier_token)); | 
					
						
							|  |  |  |     var->set_initial_value(move(initial_value)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return var; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Expression> Parser::parse_expression(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto expression = parse_primary_expression(parent); | 
					
						
							|  |  |  |     // TODO: remove eof() logic, should still work without it
 | 
					
						
							|  |  |  |     if (eof() || match(Token::Type::Semicolon)) { | 
					
						
							|  |  |  |         return expression; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     NonnullRefPtrVector<Expression> secondary_expressions; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (match_secondary_expression()) { | 
					
						
							|  |  |  |         // FIXME: Handle operator precedence
 | 
					
						
							|  |  |  |         expression = parse_secondary_expression(parent, expression); | 
					
						
							|  |  |  |         secondary_expressions.append(expression); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (size_t i = 0; secondary_expressions.size() != 0 && i < secondary_expressions.size() - 1; ++i) { | 
					
						
							|  |  |  |         secondary_expressions[i].set_parent(secondary_expressions[i + 1]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return expression; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_secondary_expression() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto type = peek().type(); | 
					
						
							|  |  |  |     return type == Token::Type::Plus | 
					
						
							|  |  |  |         || type == Token::Type::PlusEquals | 
					
						
							|  |  |  |         || type == Token::Type::Minus | 
					
						
							|  |  |  |         || type == Token::Type::MinusEquals | 
					
						
							|  |  |  |         || type == Token::Type::Asterisk | 
					
						
							|  |  |  |         || type == Token::Type::AsteriskEquals | 
					
						
							|  |  |  |         || type == Token::Type::Percent | 
					
						
							|  |  |  |         || type == Token::Type::PercentEquals | 
					
						
							|  |  |  |         || type == Token::Type::Equals | 
					
						
							|  |  |  |         || type == Token::Type::Greater | 
					
						
							|  |  |  |         || type == Token::Type::Greater | 
					
						
							|  |  |  |         || type == Token::Type::Less | 
					
						
							|  |  |  |         || type == Token::Type::LessEquals | 
					
						
							|  |  |  |         || type == Token::Type::Dot | 
					
						
							|  |  |  |         || type == Token::Type::PlusPlus | 
					
						
							|  |  |  |         || type == Token::Type::MinusMinus | 
					
						
							|  |  |  |         || type == Token::Type::And | 
					
						
							|  |  |  |         || type == Token::Type::AndEquals | 
					
						
							|  |  |  |         || type == Token::Type::Pipe | 
					
						
							|  |  |  |         || type == Token::Type::PipeEquals | 
					
						
							|  |  |  |         || type == Token::Type::Caret | 
					
						
							|  |  |  |         || type == Token::Type::CaretEquals | 
					
						
							|  |  |  |         || type == Token::Type::LessLess | 
					
						
							|  |  |  |         || type == Token::Type::LessLessEquals | 
					
						
							|  |  |  |         || type == Token::Type::GreaterGreater | 
					
						
							|  |  |  |         || type == Token::Type::GreaterGreaterEquals | 
					
						
							| 
									
										
										
										
											2021-03-27 19:20:20 +03:00
										 |  |  |         || type == Token::Type::EqualsEquals | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         || type == Token::Type::AndAnd | 
					
						
							| 
									
										
										
										
											2021-03-31 18:19:17 +03:00
										 |  |  |         || type == Token::Type::PipePipe | 
					
						
							| 
									
										
										
										
											2021-04-02 10:28:17 +03:00
										 |  |  |         || type == Token::Type::ExclamationMarkEquals | 
					
						
							| 
									
										
										
										
											2021-04-02 11:15:51 +03:00
										 |  |  |         || type == Token::Type::PipePipe | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |         || type == Token::Type::Arrow | 
					
						
							|  |  |  |         || type == Token::Type::LeftParen; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Expression> Parser::parse_primary_expression(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     // TODO: remove eof() logic, should still work without it
 | 
					
						
							|  |  |  |     if (eof()) { | 
					
						
							|  |  |  |         auto node = create_ast_node<Identifier>(parent, position(), position()); | 
					
						
							|  |  |  |         return node; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (match_unary_expression()) | 
					
						
							|  |  |  |         return parse_unary_expression(parent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (match_literal()) { | 
					
						
							|  |  |  |         return parse_literal(parent); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-29 16:52:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-31 22:21:31 +03:00
										 |  |  |     if (match_cpp_cast_expression()) | 
					
						
							|  |  |  |         return parse_cpp_cast_expression(parent); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 11:29:44 +03:00
										 |  |  |     if (match_c_style_cast_expression()) | 
					
						
							|  |  |  |         return parse_c_style_cast_expression(parent); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 11:15:22 +03:00
										 |  |  |     if (match_sizeof_expression()) | 
					
						
							| 
									
										
										
										
											2021-04-02 10:49:12 +03:00
										 |  |  |         return parse_sizeof_expression(parent); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 11:15:22 +03:00
										 |  |  |     if (match_braced_init_list()) | 
					
						
							|  |  |  |         return parse_braced_init_list(parent); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 16:52:35 +03:00
										 |  |  |     if (match_name()) { | 
					
						
							|  |  |  |         return parse_name(parent); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-29 16:52:35 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     error("could not parse primary expression"); | 
					
						
							|  |  |  |     auto token = consume(); | 
					
						
							|  |  |  |     return create_ast_node<InvalidExpression>(parent, token.start(), token.end()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_literal() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (peek().type()) { | 
					
						
							|  |  |  |     case Token::Type::Integer: | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2021-03-31 17:55:43 +03:00
										 |  |  |     case Token::Type::SingleQuotedString: | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     case Token::Type::DoubleQuotedString: | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2021-03-28 10:40:20 +03:00
										 |  |  |     case Token::Type::Float: | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     case Token::Type::Keyword: { | 
					
						
							| 
									
										
										
										
											2021-03-28 10:40:20 +03:00
										 |  |  |         return match_boolean_literal() || peek().text() == "nullptr"; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_unary_expression() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto type = peek().type(); | 
					
						
							|  |  |  |     return type == Token::Type::PlusPlus | 
					
						
							|  |  |  |         || type == Token::Type::MinusMinus | 
					
						
							|  |  |  |         || type == Token::Type::ExclamationMark | 
					
						
							|  |  |  |         || type == Token::Type::Tilde | 
					
						
							|  |  |  |         || type == Token::Type::Plus | 
					
						
							| 
									
										
										
										
											2021-04-02 10:28:17 +03:00
										 |  |  |         || type == Token::Type::Minus | 
					
						
							|  |  |  |         || type == Token::Type::And; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<UnaryExpression> Parser::parse_unary_expression(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto unary_exp = create_ast_node<UnaryExpression>(parent, position(), {}); | 
					
						
							|  |  |  |     auto op_token = consume(); | 
					
						
							|  |  |  |     UnaryOp op { UnaryOp::Invalid }; | 
					
						
							|  |  |  |     switch (op_token.type()) { | 
					
						
							|  |  |  |     case Token::Type::Minus: | 
					
						
							|  |  |  |         op = UnaryOp::Minus; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Token::Type::Plus: | 
					
						
							|  |  |  |         op = UnaryOp::Plus; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Token::Type::ExclamationMark: | 
					
						
							|  |  |  |         op = UnaryOp::Not; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Token::Type::Tilde: | 
					
						
							|  |  |  |         op = UnaryOp::BitwiseNot; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Token::Type::PlusPlus: | 
					
						
							|  |  |  |         op = UnaryOp::PlusPlus; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-04-02 10:28:17 +03:00
										 |  |  |     case Token::Type::And: | 
					
						
							|  |  |  |         op = UnaryOp::Address; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     unary_exp->set_op(op); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto lhs = parse_expression(*unary_exp); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     unary_exp->set_lhs(lhs); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     unary_exp->set_end(lhs->end()); | 
					
						
							|  |  |  |     return unary_exp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Expression> Parser::parse_literal(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (peek().type()) { | 
					
						
							|  |  |  |     case Token::Type::Integer: { | 
					
						
							|  |  |  |         auto token = consume(); | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |         return create_ast_node<NumericLiteral>(parent, token.start(), token.end(), text_of_token(token)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-31 17:55:43 +03:00
										 |  |  |     case Token::Type::SingleQuotedString: | 
					
						
							|  |  |  |         [[fallthrough]]; | 
					
						
							|  |  |  |     case Token::Type::DoubleQuotedString: | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return parse_string_literal(parent); | 
					
						
							|  |  |  |     case Token::Type::Keyword: { | 
					
						
							|  |  |  |         if (match_boolean_literal()) | 
					
						
							|  |  |  |             return parse_boolean_literal(parent); | 
					
						
							| 
									
										
										
										
											2021-03-28 10:40:20 +03:00
										 |  |  |         if (peek().text() == "nullptr") { | 
					
						
							|  |  |  |             auto token = consume(); | 
					
						
							|  |  |  |             return create_ast_node<NullPointerLiteral>(parent, token.start(), token.end()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         [[fallthrough]]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: { | 
					
						
							|  |  |  |         error("could not parse literal"); | 
					
						
							|  |  |  |         auto token = consume(); | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |         return create_ast_node<InvalidExpression>(parent, token.start(), token.end()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Expression> Parser::parse_secondary_expression(ASTNode& parent, NonnullRefPtr<Expression> lhs) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |     switch (peek().type()) { | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     case Token::Type::Plus: | 
					
						
							|  |  |  |         return parse_binary_expression(parent, lhs, BinaryOp::Addition); | 
					
						
							|  |  |  |     case Token::Type::Less: | 
					
						
							|  |  |  |         return parse_binary_expression(parent, lhs, BinaryOp::LessThan); | 
					
						
							| 
									
										
										
										
											2021-03-27 19:20:20 +03:00
										 |  |  |     case Token::Type::EqualsEquals: | 
					
						
							|  |  |  |         return parse_binary_expression(parent, lhs, BinaryOp::EqualsEquals); | 
					
						
							| 
									
										
										
										
											2021-03-31 18:19:17 +03:00
										 |  |  |     case Token::Type::ExclamationMarkEquals: | 
					
						
							|  |  |  |         return parse_binary_expression(parent, lhs, BinaryOp::NotEqual); | 
					
						
							| 
									
										
										
										
											2021-04-02 10:28:17 +03:00
										 |  |  |     case Token::Type::And: | 
					
						
							|  |  |  |         return parse_binary_expression(parent, lhs, BinaryOp::BitwiseAnd); | 
					
						
							|  |  |  |     case Token::Type::AndAnd: | 
					
						
							|  |  |  |         return parse_binary_expression(parent, lhs, BinaryOp::LogicalAnd); | 
					
						
							|  |  |  |     case Token::Type::Pipe: | 
					
						
							|  |  |  |         return parse_binary_expression(parent, lhs, BinaryOp::BitwiseOr); | 
					
						
							|  |  |  |     case Token::Type::PipePipe: | 
					
						
							|  |  |  |         return parse_binary_expression(parent, lhs, BinaryOp::LogicalOr); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:15:51 +03:00
										 |  |  |     case Token::Type::Arrow: | 
					
						
							|  |  |  |         return parse_binary_expression(parent, lhs, BinaryOp::Arrow); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     case Token::Type::Equals: | 
					
						
							|  |  |  |         return parse_assignment_expression(parent, lhs, AssignmentOp::Assignment); | 
					
						
							|  |  |  |     case Token::Type::Dot: { | 
					
						
							|  |  |  |         consume(); | 
					
						
							|  |  |  |         auto exp = create_ast_node<MemberExpression>(parent, lhs->start(), {}); | 
					
						
							|  |  |  |         lhs->set_parent(*exp); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         exp->set_object(move(lhs)); | 
					
						
							| 
									
										
										
										
											2021-04-03 14:40:13 +03:00
										 |  |  |         auto identifier_token = consume(Token::Type::Identifier); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         exp->set_property(create_ast_node<Identifier>(*exp, identifier_token.start(), identifier_token.end(), identifier_token.text())); | 
					
						
							| 
									
										
										
										
											2021-03-29 16:52:35 +03:00
										 |  |  |         exp->set_end(position()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return exp; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |     case Token::Type::LeftParen: { | 
					
						
							|  |  |  |         consume(); | 
					
						
							|  |  |  |         auto func = create_ast_node<FunctionCall>(parent, lhs->start(), {}); | 
					
						
							|  |  |  |         lhs->set_parent(*func); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         func->set_callee(move(lhs)); | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |         while (peek().type() != Token::Type::RightParen && !eof()) { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |             func->add_argument(parse_expression(*func)); | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |             if (peek().type() == Token::Type::Comma) | 
					
						
							|  |  |  |                 consume(Token::Type::Comma); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         consume(Token::Type::RightParen); | 
					
						
							|  |  |  |         func->set_end(position()); | 
					
						
							|  |  |  |         return func; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     default: { | 
					
						
							|  |  |  |         error(String::formatted("unexpected operator for expression. operator: {}", peek().to_string())); | 
					
						
							|  |  |  |         auto token = consume(); | 
					
						
							|  |  |  |         return create_ast_node<InvalidExpression>(parent, token.start(), token.end()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<BinaryExpression> Parser::parse_binary_expression(ASTNode& parent, NonnullRefPtr<Expression> lhs, BinaryOp op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     consume(); // Operator
 | 
					
						
							|  |  |  |     auto exp = create_ast_node<BinaryExpression>(parent, lhs->start(), {}); | 
					
						
							|  |  |  |     lhs->set_parent(*exp); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     exp->set_op(op); | 
					
						
							|  |  |  |     exp->set_lhs(move(lhs)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto rhs = parse_expression(exp); | 
					
						
							|  |  |  |     exp->set_end(rhs->end()); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     exp->set_rhs(move(rhs)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     return exp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<AssignmentExpression> Parser::parse_assignment_expression(ASTNode& parent, NonnullRefPtr<Expression> lhs, AssignmentOp op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     consume(); // Operator
 | 
					
						
							|  |  |  |     auto exp = create_ast_node<AssignmentExpression>(parent, lhs->start(), {}); | 
					
						
							|  |  |  |     lhs->set_parent(*exp); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     exp->set_op(op); | 
					
						
							|  |  |  |     exp->set_lhs(move(lhs)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto rhs = parse_expression(exp); | 
					
						
							|  |  |  |     exp->set_end(rhs->end()); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     exp->set_rhs(move(rhs)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     return exp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optional<Parser::DeclarationType> Parser::match_declaration_in_translation_unit() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (match_function_declaration()) | 
					
						
							|  |  |  |         return DeclarationType::Function; | 
					
						
							|  |  |  |     if (match_enum_declaration()) | 
					
						
							|  |  |  |         return DeclarationType::Enum; | 
					
						
							| 
									
										
										
										
											2021-04-19 19:41:43 +03:00
										 |  |  |     if (match_class_declaration()) | 
					
						
							|  |  |  |         return DeclarationType::Class; | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |     if (match_namespace_declaration()) | 
					
						
							|  |  |  |         return DeclarationType::Namespace; | 
					
						
							| 
									
										
										
										
											2021-03-27 18:42:32 +03:00
										 |  |  |     if (match_variable_declaration()) | 
					
						
							|  |  |  |         return DeclarationType::Variable; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  | Optional<Parser::DeclarationType> Parser::match_class_member(const StringView& class_name) | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     if (match_function_declaration()) | 
					
						
							|  |  |  |         return DeclarationType::Function; | 
					
						
							|  |  |  |     if (match_enum_declaration()) | 
					
						
							|  |  |  |         return DeclarationType::Enum; | 
					
						
							|  |  |  |     if (match_class_declaration()) | 
					
						
							|  |  |  |         return DeclarationType::Class; | 
					
						
							|  |  |  |     if (match_variable_declaration()) | 
					
						
							|  |  |  |         return DeclarationType::Variable; | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  |     if (match_constructor(class_name)) | 
					
						
							|  |  |  |         return DeclarationType::Constructor; | 
					
						
							|  |  |  |     if (match_destructor(class_name)) | 
					
						
							|  |  |  |         return DeclarationType::Destructor; | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | bool Parser::match_enum_declaration() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-20 21:51:53 +03:00
										 |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!match_keyword("enum")) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::Keyword); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (match_keyword("class")) | 
					
						
							|  |  |  |         consume(Token::Type::Keyword); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!match(Token::Type::Identifier)) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::Identifier); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return match(Token::Type::LeftCurly); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-19 19:41:43 +03:00
										 |  |  | bool Parser::match_class_declaration() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							| 
									
										
										
										
											2021-04-19 19:41:43 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  |     if (!match_keyword("struct") && !match_keyword("class")) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-06-06 21:30:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  |     consume(Token::Type::Keyword); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!match(Token::Type::Identifier)) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::Identifier); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return match(Token::Type::LeftCurly); | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_namespace_declaration() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return match_keyword("namespace"); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_function_declaration() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  |     parse_function_qualifiers(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |     if (!match_type()) | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  |     VERIFY(m_root_node); | 
					
						
							| 
									
										
										
										
											2021-04-02 13:57:52 +03:00
										 |  |  |     parse_type(get_dummy_node()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!peek(Token::Type::Identifier).has_value()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     consume(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!peek(Token::Type::LeftParen).has_value()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     consume(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |     while (consume().type() != Token::Type::RightParen && !eof()) { }; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (peek(Token::Type::Semicolon).has_value() || peek(Token::Type::LeftCurly).has_value()) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 22:32:42 +02:00
										 |  |  |     if (match_attribute_specification()) { | 
					
						
							|  |  |  |         consume_attribute_specification(); | 
					
						
							|  |  |  |         return peek(Token::Type::Semicolon).has_value(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optional<NonnullRefPtrVector<Parameter>> Parser::parse_parameter_list(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     NonnullRefPtrVector<Parameter> parameters; | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |     while (peek().type() != Token::Type::RightParen && !eof()) { | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  |         if (match_ellipsis()) { | 
					
						
							| 
									
										
										
										
											2021-07-03 11:33:01 +03:00
										 |  |  |             auto param = create_ast_node<Parameter>(parent, position(), {}, StringView {}); | 
					
						
							|  |  |  |             consume(Token::Type::Dot); | 
					
						
							|  |  |  |             consume(Token::Type::Dot); | 
					
						
							|  |  |  |             auto last_dot = consume(Token::Type::Dot); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |             param->set_ellipsis(true); | 
					
						
							| 
									
										
										
										
											2021-07-03 11:33:01 +03:00
										 |  |  |             param->set_end(last_dot.end()); | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  |             parameters.append(move(param)); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             auto type = parse_type(parent); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  |             auto name_identifier = peek(Token::Type::Identifier); | 
					
						
							|  |  |  |             if (name_identifier.has_value()) | 
					
						
							|  |  |  |                 consume(Token::Type::Identifier); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  |             StringView name; | 
					
						
							|  |  |  |             if (name_identifier.has_value()) | 
					
						
							|  |  |  |                 name = text_of_token(name_identifier.value()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |             auto param = create_ast_node<Parameter>(parent, type->start(), name_identifier.has_value() ? name_identifier.value().end() : type->end(), name); | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |             param->set_type(move(type)); | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  |             parameters.append(move(param)); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (peek(Token::Type::Comma).has_value()) | 
					
						
							|  |  |  |             consume(Token::Type::Comma); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return parameters; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_comment() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return match(Token::Type::Comment); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_whitespace() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return match(Token::Type::Whitespace); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_preprocessor() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return match(Token::Type::PreprocessorStatement) || match(Token::Type::IncludeStatement); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Parser::consume_preprocessor() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     switch (peek().type()) { | 
					
						
							|  |  |  |     case Token::Type::PreprocessorStatement: | 
					
						
							|  |  |  |         consume(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Token::Type::IncludeStatement: | 
					
						
							|  |  |  |         consume(); | 
					
						
							|  |  |  |         consume(Token::Type::IncludePath); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         error("unexpected token while parsing preprocessor statement"); | 
					
						
							|  |  |  |         consume(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optional<Token> Parser::consume_whitespace() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     return consume(Token::Type::Whitespace); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Token Parser::consume(Token::Type type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto token = consume(); | 
					
						
							|  |  |  |     if (token.type() != type) | 
					
						
							|  |  |  |         error(String::formatted("expected {} at {}:{}, found: {}", Token::type_to_string(type), token.start().line, token.start().column, Token::type_to_string(token.type()))); | 
					
						
							|  |  |  |     return token; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match(Token::Type type) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |     return peek().type() == type; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Token Parser::consume() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (eof()) { | 
					
						
							|  |  |  |         error("C++ Parser: out of tokens"); | 
					
						
							| 
									
										
										
										
											2021-03-12 13:11:41 +02:00
										 |  |  |         return { Token::Type::EOF_TOKEN, position(), position(), {} }; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     return m_tokens[m_state.token_index++]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  | Token Parser::peek(size_t offset) const | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  |     if (m_state.token_index + offset >= m_tokens.size()) | 
					
						
							| 
									
										
										
										
											2021-03-12 13:11:41 +02:00
										 |  |  |         return { Token::Type::EOF_TOKEN, position(), position(), {} }; | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  |     return m_tokens[m_state.token_index + offset]; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optional<Token> Parser::peek(Token::Type type) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto token = peek(); | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |     if (token.type() == type) | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         return token; | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Parser::save_state() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_saved_states.append(m_state); | 
					
						
							| 
									
										
										
										
											2021-07-13 22:07:05 +03:00
										 |  |  |     m_state.state_nodes.clear(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Parser::load_state() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_state = m_saved_states.take_last(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-10 21:48:08 +02:00
										 |  |  | StringView Parser::text_of_token(const Cpp::Token& token) const | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-12 15:28:30 +02:00
										 |  |  |     return token.text(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 15:53:07 +02:00
										 |  |  | String Parser::text_of_node(const ASTNode& node) const | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-12 15:53:07 +02:00
										 |  |  |     return text_in_range(node.start(), node.end()); | 
					
						
							| 
									
										
										
										
											2021-02-10 22:15:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 15:53:07 +02:00
										 |  |  | String Parser::text_in_range(Position start, Position end) const | 
					
						
							| 
									
										
										
										
											2021-07-03 11:47:41 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     for (auto token : tokens_in_range(start, end)) { | 
					
						
							|  |  |  |         builder.append(token.text()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return builder.to_string(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vector<Token> Parser::tokens_in_range(Position start, Position end) const | 
					
						
							| 
									
										
										
										
											2021-02-10 22:15:38 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-12 15:53:07 +02:00
										 |  |  |     auto start_token_index = index_of_token_at(start); | 
					
						
							|  |  |  |     auto end_node_index = index_of_token_at(end); | 
					
						
							|  |  |  |     VERIFY(start_token_index.has_value()); | 
					
						
							|  |  |  |     VERIFY(end_node_index.has_value()); | 
					
						
							| 
									
										
										
										
											2021-07-03 11:47:41 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Vector<Token> tokens; | 
					
						
							| 
									
										
										
										
											2021-03-12 15:56:30 +02:00
										 |  |  |     for (size_t i = start_token_index.value(); i <= end_node_index.value(); ++i) { | 
					
						
							| 
									
										
										
										
											2021-07-03 11:47:41 +03:00
										 |  |  |         tokens.append(m_tokens[i]); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-03 11:47:41 +03:00
										 |  |  |     return tokens; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Parser::error(StringView message) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-07-13 20:37:28 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!m_saved_states.is_empty()) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2021-07-13 22:07:05 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     if (message.is_null() || message.is_empty()) | 
					
						
							|  |  |  |         message = "<empty>"; | 
					
						
							|  |  |  |     String formatted_message; | 
					
						
							|  |  |  |     if (m_state.token_index >= m_tokens.size()) { | 
					
						
							|  |  |  |         formatted_message = String::formatted("C++ Parsed error on EOF.{}", message); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         formatted_message = String::formatted("C++ Parser error: {}. token: {} ({}:{})", | 
					
						
							|  |  |  |             message, | 
					
						
							|  |  |  |             m_state.token_index < m_tokens.size() ? text_of_token(m_tokens[m_state.token_index]) : "EOF", | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |             m_tokens[m_state.token_index].start().line, | 
					
						
							|  |  |  |             m_tokens[m_state.token_index].start().column); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-13 20:37:28 +03:00
										 |  |  |     m_errors.append(formatted_message); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_expression() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-28 10:40:20 +03:00
										 |  |  |     return match_literal() | 
					
						
							| 
									
										
										
										
											2021-05-17 10:41:01 +03:00
										 |  |  |         || match_name() | 
					
						
							| 
									
										
										
										
											2021-03-31 22:21:31 +03:00
										 |  |  |         || match_unary_expression() | 
					
						
							| 
									
										
										
										
											2021-04-02 10:49:12 +03:00
										 |  |  |         || match_cpp_cast_expression() | 
					
						
							| 
									
										
										
										
											2021-04-02 11:29:44 +03:00
										 |  |  |         || match_c_style_cast_expression() | 
					
						
							| 
									
										
										
										
											2021-04-02 11:15:22 +03:00
										 |  |  |         || match_sizeof_expression() | 
					
						
							|  |  |  |         || match_braced_init_list(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::eof() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return m_state.token_index >= m_tokens.size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Position Parser::position() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     if (m_tokens.is_empty()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     if (eof()) | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |         return m_tokens.last().end(); | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |     return peek().start(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RefPtr<ASTNode> Parser::node_at(Position pos) const | 
					
						
							| 
									
										
										
										
											2021-03-12 15:28:30 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-07-13 22:07:05 +03:00
										 |  |  |     VERIFY(m_saved_states.is_empty()); | 
					
						
							| 
									
										
										
										
											2021-03-12 15:28:30 +02:00
										 |  |  |     auto index = index_of_node_at(pos); | 
					
						
							|  |  |  |     if (!index.has_value()) | 
					
						
							|  |  |  |         return nullptr; | 
					
						
							| 
									
										
										
										
											2021-07-13 22:07:05 +03:00
										 |  |  |     return m_nodes[index.value()]; | 
					
						
							| 
									
										
										
										
											2021-03-12 15:28:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optional<size_t> Parser::index_of_node_at(Position pos) const | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(!m_tokens.is_empty()); | 
					
						
							| 
									
										
										
										
											2021-07-13 22:07:05 +03:00
										 |  |  |     VERIFY(m_saved_states.is_empty()); | 
					
						
							| 
									
										
										
										
											2021-03-12 15:28:30 +02:00
										 |  |  |     Optional<size_t> match_node_index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto node_span = [](const ASTNode& node) { | 
					
						
							|  |  |  |         VERIFY(node.end().line >= node.start().line); | 
					
						
							|  |  |  |         VERIFY((node.end().line > node.start().line) || (node.end().column >= node.start().column)); | 
					
						
							|  |  |  |         return Position { node.end().line - node.start().line, node.start().line != node.end().line ? 0 : node.end().column - node.start().column }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-13 22:07:05 +03:00
										 |  |  |     for (size_t node_index = 0; node_index < m_nodes.size(); ++node_index) { | 
					
						
							|  |  |  |         auto& node = m_nodes[node_index]; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         if (node.start() > pos || node.end() < pos) | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2021-03-12 15:28:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-13 22:07:05 +03:00
										 |  |  |         if (!match_node_index.has_value() || (node_span(node) <= node_span(m_nodes[match_node_index.value()]))) | 
					
						
							| 
									
										
										
										
											2021-03-12 15:28:30 +02:00
										 |  |  |             match_node_index = node_index; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-12 15:28:30 +02:00
										 |  |  |     return match_node_index; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optional<Token> Parser::token_at(Position pos) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-12 15:53:07 +02:00
										 |  |  |     auto index = index_of_token_at(pos); | 
					
						
							|  |  |  |     if (!index.has_value()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  |     return m_tokens[index.value()]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Optional<size_t> Parser::index_of_token_at(Position pos) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (size_t token_index = 0; token_index < m_tokens.size(); ++token_index) { | 
					
						
							|  |  |  |         auto token = m_tokens[token_index]; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         if (token.start() > pos || token.end() < pos) | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2021-03-12 15:53:07 +02:00
										 |  |  |         return token_index; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Parser::print_tokens() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (auto& token : m_tokens) { | 
					
						
							| 
									
										
										
										
											2021-05-21 14:39:42 +03:00
										 |  |  |         outln("{}", token.to_string()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-01 23:54:55 +02:00
										 |  |  | Vector<Parser::TodoEntry> Parser::get_todo_entries() const | 
					
						
							| 
									
										
										
										
											2021-05-17 22:14:59 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-01 23:54:55 +02:00
										 |  |  |     Vector<TodoEntry> ret; | 
					
						
							| 
									
										
										
										
											2021-05-17 22:14:59 +02:00
										 |  |  |     for (auto& token : m_tokens) { | 
					
						
							|  |  |  |         if (token.type() == Token::Type::Comment) { | 
					
						
							|  |  |  |             if (token.text().contains("TODO")) { | 
					
						
							| 
									
										
										
										
											2021-06-01 23:54:55 +02:00
										 |  |  |                 ret.append({ token.text(), m_filename, token.start().line, token.start().column }); | 
					
						
							| 
									
										
										
										
											2021-05-17 22:14:59 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | NonnullRefPtr<StringLiteral> Parser::parse_string_literal(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     Optional<size_t> start_token_index; | 
					
						
							|  |  |  |     Optional<size_t> end_token_index; | 
					
						
							|  |  |  |     while (!eof()) { | 
					
						
							|  |  |  |         auto token = peek(); | 
					
						
							| 
									
										
										
										
											2021-03-31 17:55:43 +03:00
										 |  |  |         if (token.type() != Token::Type::DoubleQuotedString && token.type() != Token::Type::SingleQuotedString && token.type() != Token::Type::EscapeSequence) { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |             VERIFY(start_token_index.has_value()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |             end_token_index = m_state.token_index - 1; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!start_token_index.has_value()) | 
					
						
							|  |  |  |             start_token_index = m_state.token_index; | 
					
						
							|  |  |  |         consume(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-02-10 22:15:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // String was not terminated
 | 
					
						
							|  |  |  |     if (!end_token_index.has_value()) { | 
					
						
							|  |  |  |         end_token_index = m_tokens.size() - 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(start_token_index.has_value()); | 
					
						
							|  |  |  |     VERIFY(end_token_index.has_value()); | 
					
						
							| 
									
										
										
										
											2021-02-10 22:15:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     Token start_token = m_tokens[start_token_index.value()]; | 
					
						
							|  |  |  |     Token end_token = m_tokens[end_token_index.value()]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 15:53:07 +02:00
										 |  |  |     auto text = text_in_range(start_token.start(), end_token.end()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto string_literal = create_ast_node<StringLiteral>(parent, start_token.start(), end_token.end()); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     string_literal->set_value(move(text)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     return string_literal; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<ReturnStatement> Parser::parse_return_statement(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto return_statement = create_ast_node<ReturnStatement>(parent, position(), {}); | 
					
						
							|  |  |  |     consume(Token::Type::Keyword); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |     if (!peek(Token::Type::Semicolon).has_value()) { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         return_statement->set_value(parse_expression(*return_statement)); | 
					
						
							| 
									
										
										
										
											2021-03-27 19:18:18 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     return_statement->set_end(position()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     return return_statement; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<EnumDeclaration> Parser::parse_enum_declaration(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto enum_decl = create_ast_node<EnumDeclaration>(parent, position(), {}); | 
					
						
							|  |  |  |     consume_keyword("enum"); | 
					
						
							| 
									
										
										
										
											2021-06-20 21:51:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (match_keyword("class")) { | 
					
						
							|  |  |  |         consume(Token::Type::Keyword); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         enum_decl->set_type(EnumDeclaration::Type::EnumClass); | 
					
						
							| 
									
										
										
										
											2021-06-20 21:51:53 +03:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         enum_decl->set_type(EnumDeclaration::Type::RegularEnum); | 
					
						
							| 
									
										
										
										
											2021-06-20 21:51:53 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto name_token = consume(Token::Type::Identifier); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     enum_decl->set_name(text_of_token(name_token)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     consume(Token::Type::LeftCurly); | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |     while (!eof() && peek().type() != Token::Type::RightCurly) { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         enum_decl->add_entry(text_of_token(consume(Token::Type::Identifier))); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         if (peek().type() != Token::Type::Comma) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         consume(Token::Type::Comma); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     consume(Token::Type::RightCurly); | 
					
						
							|  |  |  |     consume(Token::Type::Semicolon); | 
					
						
							|  |  |  |     enum_decl->set_end(position()); | 
					
						
							|  |  |  |     return enum_decl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Token Parser::consume_keyword(const String& keyword) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto token = consume(); | 
					
						
							|  |  |  |     if (token.type() != Token::Type::Keyword) { | 
					
						
							|  |  |  |         error(String::formatted("unexpected token: {}, expected Keyword", token.to_string())); | 
					
						
							|  |  |  |         return token; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (text_of_token(token) != keyword) { | 
					
						
							|  |  |  |         error(String::formatted("unexpected keyword: {}, expected {}", text_of_token(token), keyword)); | 
					
						
							|  |  |  |         return token; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return token; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_keyword(const String& keyword) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto token = peek(); | 
					
						
							|  |  |  |     if (token.type() != Token::Type::Keyword) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (text_of_token(token) != keyword) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  | NonnullRefPtr<StructOrClassDeclaration> Parser::parse_class_declaration(ASTNode& parent) | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     auto type_token = consume(Token::Type::Keyword); | 
					
						
							|  |  |  |     StructOrClassDeclaration::Type type {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (type_token.text() == "struct") | 
					
						
							|  |  |  |         type = StructOrClassDeclaration::Type::Struct; | 
					
						
							|  |  |  |     if (type_token.text() == "class") | 
					
						
							|  |  |  |         type = StructOrClassDeclaration::Type::Class; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto decl = create_ast_node<StructOrClassDeclaration>(parent, position(), {}, type); | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto name_token = consume(Token::Type::Identifier); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     decl->set_name(text_of_token(name_token)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::LeftCurly); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |     while (!eof() && peek().type() != Token::Type::RightCurly) { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         decl->set_members(parse_class_members(*decl)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::RightCurly); | 
					
						
							|  |  |  |     consume(Token::Type::Semicolon); | 
					
						
							|  |  |  |     decl->set_end(position()); | 
					
						
							|  |  |  |     return decl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<BooleanLiteral> Parser::parse_boolean_literal(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto token = consume(Token::Type::Keyword); | 
					
						
							|  |  |  |     auto text = text_of_token(token); | 
					
						
							|  |  |  |     // text == "true" || text == "false";
 | 
					
						
							|  |  |  |     bool value = (text == "true"); | 
					
						
							|  |  |  |     return create_ast_node<BooleanLiteral>(parent, token.start(), token.end(), value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_boolean_literal() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto token = peek(); | 
					
						
							|  |  |  |     if (token.type() != Token::Type::Keyword) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     auto text = text_of_token(token); | 
					
						
							|  |  |  |     return text == "true" || text == "false"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Type> Parser::parse_type(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |     if (!match_named_type()) { | 
					
						
							|  |  |  |         error("expected named named_type"); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |         auto token = consume(); | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |         return create_ast_node<NamedType>(parent, token.start(), token.end()); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |     auto named_type = create_ast_node<NamedType>(parent, position(), {}); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-28 18:40:45 +02:00
										 |  |  |     auto qualifiers = parse_type_qualifiers(); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     named_type->set_qualifiers(move(qualifiers)); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-17 10:40:19 +03:00
										 |  |  |     if (match_keyword("auto")) { | 
					
						
							|  |  |  |         consume(Token::Type::Keyword); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         named_type->set_auto(true); | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |         named_type->set_end(position()); | 
					
						
							|  |  |  |         return named_type; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-02 10:36:48 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |     if (match_keyword("struct")) { | 
					
						
							|  |  |  |         consume(Token::Type::Keyword); // Consume struct prefix
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-17 10:40:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |     if (!match_name()) { | 
					
						
							|  |  |  |         named_type->set_end(position()); | 
					
						
							|  |  |  |         error(String::formatted("expected name instead of: {}", peek().text())); | 
					
						
							|  |  |  |         return named_type; | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     named_type->set_name(parse_name(*named_type)); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |     NonnullRefPtr<Type> type = named_type; | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |     while (!eof() && peek().type() == Token::Type::Asterisk) { | 
					
						
							|  |  |  |         type->set_end(position()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |         auto asterisk = consume(); | 
					
						
							| 
									
										
										
										
											2021-07-03 11:34:18 +03:00
										 |  |  |         auto ptr = create_ast_node<Pointer>(parent, type->start(), asterisk.end()); | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  |         type->set_parent(*ptr); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         ptr->set_pointee(type); | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |         ptr->set_end(position()); | 
					
						
							| 
									
										
										
										
											2021-06-26 15:34:23 +03:00
										 |  |  |         type = ptr; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-28 11:55:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     type->set_end(position()); | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |     return type; | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<ForStatement> Parser::parse_for_statement(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     auto for_statement = create_ast_node<ForStatement>(parent, position(), {}); | 
					
						
							|  |  |  |     consume(Token::Type::Keyword); | 
					
						
							|  |  |  |     consume(Token::Type::LeftParen); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:02:14 +03:00
										 |  |  |     if (peek().type() != Token::Type::Semicolon) | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         for_statement->set_init(parse_variable_declaration(*for_statement, false)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     consume(Token::Type::Semicolon); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:02:14 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (peek().type() != Token::Type::Semicolon) | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         for_statement->set_test(parse_expression(*for_statement)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     consume(Token::Type::Semicolon); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:02:14 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (peek().type() != Token::Type::RightParen) | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         for_statement->set_update(parse_expression(*for_statement)); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     consume(Token::Type::RightParen); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:02:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     for_statement->set_body(parse_statement(*for_statement)); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:02:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     for_statement->set_end(for_statement->body()->end()); | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  |     return for_statement; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-29 12:03:02 +02:00
										 |  |  | NonnullRefPtr<IfStatement> Parser::parse_if_statement(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-01-29 12:03:02 +02:00
										 |  |  |     auto if_statement = create_ast_node<IfStatement>(parent, position(), {}); | 
					
						
							|  |  |  |     consume(Token::Type::Keyword); | 
					
						
							|  |  |  |     consume(Token::Type::LeftParen); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     if_statement->set_predicate(parse_expression(*if_statement)); | 
					
						
							| 
									
										
										
										
											2021-01-29 12:03:02 +02:00
										 |  |  |     consume(Token::Type::RightParen); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     if_statement->set_then_statement(parse_statement(*if_statement)); | 
					
						
							| 
									
										
										
										
											2021-01-29 12:03:02 +02:00
										 |  |  |     if (match_keyword("else")) { | 
					
						
							|  |  |  |         consume(Token::Type::Keyword); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         if_statement->set_else_statement(parse_statement(*if_statement)); | 
					
						
							|  |  |  |         if_statement->set_end(if_statement->else_statement()->end()); | 
					
						
							| 
									
										
										
										
											2021-01-29 12:03:02 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         if_statement->set_end(if_statement->then_statement()->end()); | 
					
						
							| 
									
										
										
										
											2021-01-29 12:03:02 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     return if_statement; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-02-28 18:40:45 +02:00
										 |  |  | Vector<StringView> Parser::parse_type_qualifiers() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-02-28 18:40:45 +02:00
										 |  |  |     Vector<StringView> qualifiers; | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |     while (!eof()) { | 
					
						
							| 
									
										
										
										
											2021-02-28 18:40:45 +02:00
										 |  |  |         auto token = peek(); | 
					
						
							|  |  |  |         if (token.type() != Token::Type::Keyword) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         auto text = text_of_token(token); | 
					
						
							| 
									
										
										
										
											2021-07-28 04:06:45 +04:30
										 |  |  |         if (text == "static" || text == "const" || text == "extern") { | 
					
						
							| 
									
										
										
										
											2021-02-28 18:40:45 +02:00
										 |  |  |             qualifiers.append(text); | 
					
						
							|  |  |  |             consume(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return qualifiers; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | Vector<StringView> Parser::parse_function_qualifiers() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  |     Vector<StringView> qualifiers; | 
					
						
							|  |  |  |     while (!eof()) { | 
					
						
							|  |  |  |         auto token = peek(); | 
					
						
							|  |  |  |         if (token.type() != Token::Type::Keyword) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         auto text = text_of_token(token); | 
					
						
							| 
									
										
										
										
											2021-07-28 04:06:45 +04:30
										 |  |  |         if (text == "static" || text == "inline" || text == "extern") { | 
					
						
							| 
									
										
										
										
											2021-03-27 19:19:53 +03:00
										 |  |  |             qualifiers.append(text); | 
					
						
							|  |  |  |             consume(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return qualifiers; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 22:32:42 +02:00
										 |  |  | bool Parser::match_attribute_specification() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return text_of_token(peek()) == "__attribute__"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void Parser::consume_attribute_specification() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     consume(); // __attribute__
 | 
					
						
							|  |  |  |     consume(Token::Type::LeftParen); | 
					
						
							|  |  |  |     size_t left_count = 1; | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |     while (!eof()) { | 
					
						
							| 
									
										
										
										
											2021-03-01 22:32:42 +02:00
										 |  |  |         auto token = consume(); | 
					
						
							|  |  |  |         if (token.type() == Token::Type::LeftParen) { | 
					
						
							|  |  |  |             ++left_count; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (token.type() == Token::Type::RightParen) { | 
					
						
							|  |  |  |             --left_count; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  |         if (left_count == 0) | 
					
						
							| 
									
										
										
										
											2021-03-01 22:32:42 +02:00
										 |  |  |             return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  | bool Parser::match_ellipsis() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_state.token_index > m_tokens.size() - 3) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-07-03 11:33:01 +03:00
										 |  |  |     return peek().type() == Token::Type::Dot && peek(1).type() == Token::Type::Dot && peek(2).type() == Token::Type::Dot; | 
					
						
							| 
									
										
										
										
											2021-03-01 22:33:46 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-12 17:04:08 +02:00
										 |  |  | void Parser::add_tokens_for_preprocessor(Token& replaced_token, Preprocessor::DefinedValue& definition) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!definition.value.has_value()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     Lexer lexer(definition.value.value()); | 
					
						
							|  |  |  |     for (auto token : lexer.lex()) { | 
					
						
							|  |  |  |         if (token.type() == Token::Type::Whitespace) | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2021-03-12 12:46:40 +02:00
										 |  |  |         token.set_start(replaced_token.start()); | 
					
						
							|  |  |  |         token.set_end(replaced_token.end()); | 
					
						
							| 
									
										
										
										
											2021-03-12 17:04:08 +02:00
										 |  |  |         m_tokens.append(move(token)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-01 22:32:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  | NonnullRefPtr<NamespaceDeclaration> Parser::parse_namespace_declaration(ASTNode& parent, bool is_nested_namespace) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto namespace_decl = create_ast_node<NamespaceDeclaration>(parent, position(), {}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!is_nested_namespace) | 
					
						
							|  |  |  |         consume(Token::Type::Keyword); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto name_token = consume(Token::Type::Identifier); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     namespace_decl->set_name(name_token.text()); | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (peek().type() == Token::Type::ColonColon) { | 
					
						
							|  |  |  |         consume(Token::Type::ColonColon); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         namespace_decl->add_declaration(parse_namespace_declaration(*namespace_decl, true)); | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |         namespace_decl->set_end(position()); | 
					
						
							|  |  |  |         return namespace_decl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::LeftCurly); | 
					
						
							|  |  |  |     while (!eof() && peek().type() != Token::Type::RightCurly) { | 
					
						
							|  |  |  |         auto declaration = parse_single_declaration_in_translation_unit(*namespace_decl); | 
					
						
							|  |  |  |         if (declaration) { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |             namespace_decl->add_declaration(declaration.release_nonnull()); | 
					
						
							| 
									
										
										
										
											2021-03-19 21:47:43 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             error("unexpected token"); | 
					
						
							|  |  |  |             consume(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     consume(Token::Type::RightCurly); | 
					
						
							|  |  |  |     namespace_decl->set_end(position()); | 
					
						
							|  |  |  |     return namespace_decl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 16:52:35 +03:00
										 |  |  | bool Parser::match_name() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto type = peek().type(); | 
					
						
							|  |  |  |     return type == Token::Type::Identifier || type == Token::Type::KnownType; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Name> Parser::parse_name(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-26 17:23:56 +03:00
										 |  |  |     LOG_SCOPE(); | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |     NonnullRefPtr<Name> name_node = create_ast_node<Name>(parent, position(), {}); | 
					
						
							| 
									
										
										
										
											2021-05-15 09:44:31 +03:00
										 |  |  |     while (!eof() && (peek().type() == Token::Type::Identifier || peek().type() == Token::Type::KnownType) && peek(1).type() == Token::Type::ColonColon) { | 
					
						
							| 
									
										
										
										
											2021-03-29 16:52:35 +03:00
										 |  |  |         auto token = consume(); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         name_node->add_to_scope(create_ast_node<Identifier>(*name_node, token.start(), token.end(), token.text())); | 
					
						
							| 
									
										
										
										
											2021-05-15 09:44:31 +03:00
										 |  |  |         consume(Token::Type::ColonColon); | 
					
						
							| 
									
										
										
										
											2021-03-29 16:52:35 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-15 09:44:31 +03:00
										 |  |  |     if (peek().type() == Token::Type::Identifier || peek().type() == Token::Type::KnownType) { | 
					
						
							|  |  |  |         auto token = consume(); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         name_node->set_name(create_ast_node<Identifier>(*name_node, token.start(), token.end(), token.text())); | 
					
						
							| 
									
										
										
										
											2021-05-15 09:44:31 +03:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         name_node->set_end(position()); | 
					
						
							|  |  |  |         return name_node; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (match_template_arguments()) { | 
					
						
							|  |  |  |         consume(Token::Type::Less); | 
					
						
							|  |  |  |         NonnullRefPtr<TemplatizedName> templatized_name = create_ast_node<TemplatizedName>(parent, name_node->start(), {}); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         templatized_name->set_name(name_node->name()); | 
					
						
							|  |  |  |         templatized_name->set_scope(name_node->scope()); | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |         name_node->set_end(position()); | 
					
						
							|  |  |  |         name_node = templatized_name; | 
					
						
							|  |  |  |         while (peek().type() != Token::Type::Greater && !eof()) { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |             templatized_name->add_template_argument(parse_type(*templatized_name)); | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |             if (peek().type() == Token::Type::Comma) | 
					
						
							|  |  |  |                 consume(Token::Type::Comma); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         consume(Token::Type::Greater); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-29 16:52:35 +03:00
										 |  |  |     name_node->set_end(position()); | 
					
						
							|  |  |  |     return name_node; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-31 22:21:31 +03:00
										 |  |  | bool Parser::match_cpp_cast_expression() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto token = consume(); | 
					
						
							|  |  |  |     if (token.type() != Token::Type::Keyword) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto text = token.text(); | 
					
						
							|  |  |  |     if (text == "static_cast" || text == "reinterpret_cast" || text == "dynamic_cast" || text == "const_cast") | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 11:29:44 +03:00
										 |  |  | bool Parser::match_c_style_cast_expression() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (consume().type() != Token::Type::LeftParen) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-06 19:43:43 +03:00
										 |  |  |     if (!match_type()) | 
					
						
							| 
									
										
										
										
											2021-04-02 11:29:44 +03:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-04-02 13:57:52 +03:00
										 |  |  |     parse_type(get_dummy_node()); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:29:44 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (consume().type() != Token::Type::RightParen) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!match_expression()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<CStyleCastExpression> Parser::parse_c_style_cast_expression(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto parse_exp = create_ast_node<CStyleCastExpression>(parent, position(), {}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::LeftParen); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     parse_exp->set_type(parse_type(*parse_exp)); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:29:44 +03:00
										 |  |  |     consume(Token::Type::RightParen); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     parse_exp->set_expression(parse_expression(*parse_exp)); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:29:44 +03:00
										 |  |  |     parse_exp->set_end(position()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return parse_exp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-31 22:21:31 +03:00
										 |  |  | NonnullRefPtr<CppCastExpression> Parser::parse_cpp_cast_expression(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto cast_expression = create_ast_node<CppCastExpression>(parent, position(), {}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     cast_expression->set_cast_type(consume(Token::Type::Keyword).text()); | 
					
						
							| 
									
										
										
										
											2021-03-31 22:21:31 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::Less); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     cast_expression->set_type(parse_type(*cast_expression)); | 
					
						
							| 
									
										
										
										
											2021-03-31 22:21:31 +03:00
										 |  |  |     consume(Token::Type::Greater); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::LeftParen); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     cast_expression->set_expression(parse_expression(*cast_expression)); | 
					
						
							| 
									
										
										
										
											2021-03-31 22:21:31 +03:00
										 |  |  |     consume(Token::Type::RightParen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cast_expression->set_end(position()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return cast_expression; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 10:49:12 +03:00
										 |  |  | bool Parser::match_sizeof_expression() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return match_keyword("sizeof"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<SizeofExpression> Parser::parse_sizeof_expression(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto exp = create_ast_node<SizeofExpression>(parent, position(), {}); | 
					
						
							|  |  |  |     consume(Token::Type::Keyword); | 
					
						
							|  |  |  |     consume(Token::Type::LeftParen); | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     exp->set_type(parse_type(parent)); | 
					
						
							| 
									
										
										
										
											2021-04-02 10:49:12 +03:00
										 |  |  |     consume(Token::Type::RightParen); | 
					
						
							|  |  |  |     exp->set_end(position()); | 
					
						
							|  |  |  |     return exp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 11:15:22 +03:00
										 |  |  | bool Parser::match_braced_init_list() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return match(Token::Type::LeftCurly); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<BracedInitList> Parser::parse_braced_init_list(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto init_list = create_ast_node<BracedInitList>(parent, position(), {}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::LeftCurly); | 
					
						
							|  |  |  |     while (!eof() && peek().type() != Token::Type::RightCurly) { | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |         init_list->add_expression(parse_expression(*init_list)); | 
					
						
							| 
									
										
										
										
											2021-04-02 11:15:22 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     consume(Token::Type::RightCurly); | 
					
						
							|  |  |  |     init_list->set_end(position()); | 
					
						
							|  |  |  |     return init_list; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  | NonnullRefPtrVector<Declaration> Parser::parse_class_members(StructOrClassDeclaration& parent) | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  |     auto& class_name = parent.name(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  |     NonnullRefPtrVector<Declaration> members; | 
					
						
							|  |  |  |     while (!eof() && peek().type() != Token::Type::RightCurly) { | 
					
						
							| 
									
										
										
										
											2021-06-06 21:30:53 +03:00
										 |  |  |         if (match_access_specifier()) | 
					
						
							|  |  |  |             consume_access_specifier(); // FIXME: Do not ignore access specifiers
 | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  |         auto member_type = match_class_member(class_name); | 
					
						
							| 
									
										
										
										
											2021-06-05 17:57:13 +03:00
										 |  |  |         if (member_type.has_value()) { | 
					
						
							|  |  |  |             members.append(parse_declaration(parent, member_type.value())); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             error("Expected class member"); | 
					
						
							|  |  |  |             consume(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return members; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-04-02 11:15:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-06 21:30:53 +03:00
										 |  |  | bool Parser::match_access_specifier() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (peek(1).type() != Token::Type::Colon) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return match_keyword("private") || match_keyword("protected") || match_keyword("public"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Parser::consume_access_specifier() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     consume(Token::Type::Keyword); | 
					
						
							|  |  |  |     consume(Token::Type::Colon); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  | bool Parser::match_constructor(const StringView& class_name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto token = consume(); | 
					
						
							|  |  |  |     if (token.text() != class_name) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!peek(Token::Type::LeftParen).has_value()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     consume(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (consume().type() != Token::Type::RightParen && !eof()) { }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (peek(Token::Type::Semicolon).has_value() || peek(Token::Type::LeftCurly).has_value()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parser::match_destructor(const StringView& class_name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     save_state(); | 
					
						
							|  |  |  |     ScopeGuard state_guard = [this] { load_state(); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!match(Token::Type::Tilde)) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     consume(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto token = peek(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (token.text() != class_name) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     consume(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!peek(Token::Type::LeftParen).has_value()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     consume(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (consume().type() != Token::Type::RightParen && !eof()) { }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (peek(Token::Type::Semicolon).has_value() || peek(Token::Type::LeftCurly).has_value()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Parser::parse_constructor_or_destructor_impl(FunctionDeclaration& func, CtorOrDtor type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (type == CtorOrDtor::Dtor) | 
					
						
							|  |  |  |         consume(Token::Type::Tilde); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto name_token = consume(); | 
					
						
							|  |  |  |     if (name_token.type() != Token::Type::Identifier && name_token.type() != Token::Type::KnownType) { | 
					
						
							|  |  |  |         error("Unexpected constructor name"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     func.set_name(name_token.text()); | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::LeftParen); | 
					
						
							|  |  |  |     auto parameters = parse_parameter_list(func); | 
					
						
							|  |  |  |     if (parameters.has_value()) { | 
					
						
							|  |  |  |         if (type == CtorOrDtor::Dtor && !parameters->is_empty()) | 
					
						
							|  |  |  |             error("Destructor declaration that takes parameters"); | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |             func.set_parameters(parameters.value()); | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consume(Token::Type::RightParen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // TODO: Parse =default, =delete.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     RefPtr<FunctionDefinition> body; | 
					
						
							|  |  |  |     Position ctor_end {}; | 
					
						
							|  |  |  |     if (peek(Token::Type::LeftCurly).has_value()) { | 
					
						
							|  |  |  |         body = parse_function_definition(func); | 
					
						
							|  |  |  |         ctor_end = body->end(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ctor_end = position(); | 
					
						
							|  |  |  |         if (match_attribute_specification()) | 
					
						
							|  |  |  |             consume_attribute_specification(); // we don't use the value of __attribute__
 | 
					
						
							|  |  |  |         consume(Token::Type::Semicolon); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-06 22:44:20 +03:00
										 |  |  |     func.set_definition(move(body)); | 
					
						
							| 
									
										
										
										
											2021-06-07 23:14:26 +03:00
										 |  |  |     func.set_end(ctor_end); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Constructor> Parser::parse_constructor(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto ctor = create_ast_node<Constructor>(parent, position(), {}); | 
					
						
							|  |  |  |     parse_constructor_or_destructor_impl(*ctor, CtorOrDtor::Ctor); | 
					
						
							|  |  |  |     return ctor; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<Destructor> Parser::parse_destructor(ASTNode& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto ctor = create_ast_node<Destructor>(parent, position(), {}); | 
					
						
							|  |  |  |     parse_constructor_or_destructor_impl(*ctor, CtorOrDtor::Dtor); | 
					
						
							|  |  |  |     return ctor; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 16:47:20 +02:00
										 |  |  | } |